Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(apm): Sampling of traces #2500

Merged
merged 35 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
94a9e2e
fix(apm): Set sampled to true by default
HazAT Mar 18, 2020
a92c730
meta: Changelog
HazAT Mar 18, 2020
715bd45
fix(apm): Sampling
HazAT Mar 18, 2020
c82f1d8
ref: Remove set default op
HazAT Mar 18, 2020
7c8d803
fix: Sampling decision
HazAT Mar 18, 2020
895c188
ref: Add comment
HazAT Mar 18, 2020
b0870b6
ref: typo
HazAT Mar 18, 2020
a5b5f2b
ref: Changes to docblock
HazAT Mar 18, 2020
2c662dc
ref: Change message
HazAT Mar 18, 2020
b96e512
Apply suggestions from code review
HazAT Mar 18, 2020
4139da7
Update packages/types/src/options.ts
HazAT Mar 18, 2020
5a66e0b
Update packages/types/src/options.ts
HazAT Mar 18, 2020
450259e
ref: Remove deprecated parts
HazAT Mar 18, 2020
b29a8b4
Merge branch 'apm/set-sampled' of github.com:getsentry/sentry-javascr…
HazAT Mar 18, 2020
86ce10f
fix: Maxlen
HazAT Mar 18, 2020
a1b2496
ref: Rework when and how integrations are setup
HazAT Mar 18, 2020
ea581e7
ref(apm): Send a span if it's not a child
HazAT Mar 18, 2020
3583578
ref: Tracing integration
HazAT Mar 18, 2020
2bbd2e7
fix: tests
HazAT Mar 18, 2020
c3f2750
fix: Span / Transaction creation
HazAT Mar 18, 2020
de8fefa
ref: CodeReview
HazAT Mar 18, 2020
29f392e
fix: Setup integrations when after we bound a client to the hub
HazAT Mar 18, 2020
878a8fc
ref: CodeReview
HazAT Mar 18, 2020
a2733e6
fix: tests
HazAT Mar 18, 2020
74a9894
Update packages/types/src/span.ts
HazAT Mar 18, 2020
319fe10
Merge branch 'apm/set-sampled' of github.com:getsentry/sentry-javascr…
HazAT Mar 18, 2020
4332b35
ref: CodeReview
HazAT Mar 18, 2020
7a114f5
ref: CodeReview
HazAT Mar 18, 2020
a695cd9
fix: Tests
HazAT Mar 18, 2020
498e3ff
ref: Refactor SpanRecorder -> SpanList
HazAT Mar 19, 2020
26bee09
ref: Rename back to SpanRecorder to be consistent with Python
HazAT Mar 19, 2020
a2351ab
ref: SpanRecorder
HazAT Mar 19, 2020
0ad436e
ref: Remove makeRoot
HazAT Mar 19, 2020
6d471b9
ref: Changelog
HazAT Mar 19, 2020
106905d
meta: Changelog
HazAT Mar 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

- [apm] fix: Sampling of traces work now only depending on the client option `tracesSampleRate` (#2500)
- [apm] fix: Remove internal `forceNoChild` parameter from `hub.startSpan` (#2500)
- [apm] fix: Made constructor of `Span` internal, only use `hub.startSpan` (#2500)
- [apm] ref: Remove status from tags in transaction (#2497)
- [browser] fix: Respect breadcrumbs sentry:false option (#2499)

## 5.14.2

- [apm] fix: Use Performance API for timings when available, including Web Workers (#2492)
Expand Down
47 changes: 22 additions & 25 deletions packages/apm/src/hubextensions.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import { getMainCarrier, Hub } from '@sentry/hub';
import { SpanContext } from '@sentry/types';
import { isInstanceOf } from '@sentry/utils';

import { Span } from './span';

/**
* Checks whether given value is instance of Span
* @param span value to check
*/
function isSpanInstance(span: unknown): span is Span {
return isInstanceOf(span, Span);
}

/** Returns all trace headers that are currently on the top scope. */
function traceHeaders(): { [key: string]: string } {
// @ts-ignore
Expand All @@ -33,36 +24,42 @@ function traceHeaders(): { [key: string]: string } {
* and attach a `SpanRecorder`. If it's of type `SpanContext` and there is already a `Span` on the Scope,
* the created Span will have a reference to it and become it's child. Otherwise it'll crete a new `Span`.
*
* @param span Already constructed span which should be started or properties with which the span should be created
* @param spanContext Already constructed span or properties with which the span should be created
*/
function startSpan(spanOrSpanContext?: Span | SpanContext, forceNoChild: boolean = false): Span {
function startSpan(spanContext?: SpanContext): Span {
// @ts-ignore
const that = this as Hub;
const scope = that.getScope();
const client = that.getClient();
const hub = this as Hub;
const scope = hub.getScope();
const client = hub.getClient();
let span;

if (!isSpanInstance(spanOrSpanContext) && !forceNoChild) {
if (scope) {
const parentSpan = scope.getSpan() as Span;
if (parentSpan) {
span = parentSpan.child(spanOrSpanContext);
}
// This flag determines if we already added the span as a child to the span that currently lives on the scope
// If we do not have this, we will add it later on twice to the span recorder and therefore have too many spans
let addedAsChild = false;

if (scope) {
const parentSpan = scope.getSpan() as Span;
if (parentSpan) {
span = parentSpan.child(spanContext);
addedAsChild = true;
}
}

if (!isSpanInstance(span)) {
span = new Span(spanOrSpanContext, that);
if (!span) {
span = new Span(spanContext, hub);
}

if (span.sampled === undefined && span.transaction !== undefined) {
// We only roll the dice on sampling for "root" spans (transactions) because the childs inherit this state
if (span.sampled === undefined && span.isRootSpan()) {
const sampleRate = (client && client.getOptions().tracesSampleRate) || 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The || 0 here hides a configuration error or the unavailability of client, and has bitten us.

tracesSampleRate is already defaulted when setting the client options, I think we should not do the || 0 here, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, isn't it a programming error if client is undefined?

Shouldn't we be able to write simply:

Suggested change
const sampleRate = (client && client.getOptions().tracesSampleRate) || 0;
const sampleRate = client.getOptions().tracesSampleRate;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Client can be optional on the hub, that's why we need it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no client, then sampleRate can only be 0, okay.
Wouldn't this be a case to log a debug message? We debug log when the noop transport is in use in the Go SDK => when one sees that in the debug log, it is obvious why events are not sent. Here it seems like a similar situation, if there is no client we can't ever send any event, the SDK is somewhat disabled.

span.sampled = Math.random() < sampleRate;
}

if (span.sampled) {
// We only want to create a span list if we sampled the transaction
// in case we will discard the span anyway because sampled == false, we safe memory and do not store child spans
if (span.sampled && !addedAsChild) {
const experimentsOptions = (client && client.getOptions()._experiments) || {};
span.initFinishedSpans(experimentsOptions.maxSpans as number);
span.initSpanRecorder(experimentsOptions.maxSpans as number);
}

return span;
Expand Down
Loading