Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 23 additions & 6 deletions packages/core/src/tracing/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -378,15 +378,18 @@ function createChildOrRootSpan({
client?.recordDroppedEvent('ignored', 'span');
}

return new SentryNonRecordingSpan({
const ignoredSpan = new SentryNonRecordingSpan({
dropReason: 'ignored',
traceId: parentSpan?.spanContext().traceId ?? scope.getPropagationContext().traceId,
});
setCapturedScopesOnSpan(ignoredSpan, scope, isolationScope);

return ignoredSpan;
}

let span: Span;
if (parentSpan && !forceTransaction) {
span = _startChildSpan(parentSpan, scope, spanArguments);
span = _startChildSpan(parentSpan, scope, spanArguments, isolationScope);
addChildSpanToSpan(parentSpan, span);
} else if (parentSpan) {
// If we forced a transaction but have a parent span, make sure to continue from the parent span, not the scope
Expand All @@ -401,6 +404,7 @@ function createChildOrRootSpan({
...spanArguments,
},
scope,
isolationScope,
parentSampled,
);

Expand All @@ -423,6 +427,7 @@ function createChildOrRootSpan({
...spanArguments,
},
scope,
isolationScope,
parentSampled,
);

Expand All @@ -433,8 +438,6 @@ function createChildOrRootSpan({

logSpanStart(span);

setCapturedScopesOnSpan(span, scope, isolationScope);

return span;
}

Expand Down Expand Up @@ -465,7 +468,12 @@ function getAcs(): AsyncContextStrategy {
return getAsyncContextStrategy(carrier);
}

function _startRootSpan(spanArguments: SentrySpanArguments, scope: Scope, parentSampled?: boolean): SentrySpan {
function _startRootSpan(
spanArguments: SentrySpanArguments,
scope: Scope,
isolationScope: Scope,
parentSampled?: boolean,
): SentrySpan {
const client = getClient();
const options: Partial<ClientOptions> = client?.getOptions() || {};

Expand Down Expand Up @@ -512,6 +520,8 @@ function _startRootSpan(spanArguments: SentrySpanArguments, scope: Scope, parent
client.recordDroppedEvent('sample_rate', hasSpanStreamingEnabled(client) ? 'span' : 'transaction');
}

setCapturedScopesOnSpan(rootSpan, scope, isolationScope);

if (client) {
client.emit('spanStart', rootSpan);
}
Expand All @@ -523,7 +533,12 @@ function _startRootSpan(spanArguments: SentrySpanArguments, scope: Scope, parent
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`.
* This inherits the sampling decision from the parent span.
*/
function _startChildSpan(parentSpan: Span, scope: Scope, spanArguments: SentrySpanArguments): Span {
function _startChildSpan(
parentSpan: Span,
scope: Scope,
spanArguments: SentrySpanArguments,
isolationScope: Scope,
): Span {
const { spanId, traceId } = parentSpan.spanContext();
const isTracingSuppressed = _isTracingSuppressed(scope);
const sampled = isTracingSuppressed ? false : spanIsSampled(parentSpan);
Expand All @@ -539,6 +554,8 @@ function _startChildSpan(parentSpan: Span, scope: Scope, spanArguments: SentrySp

addChildSpanToSpan(parentSpan, childSpan);

setCapturedScopesOnSpan(childSpan, scope, isolationScope);

const client = getClient();

if (!client) {
Expand Down
46 changes: 46 additions & 0 deletions packages/core/test/lib/tracing/trace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2398,6 +2398,36 @@ describe('span hooks', () => {
expect(startedSpans).toEqual(['span1', 'span2', 'span3', 'span5', 'span4']);
expect(endedSpans).toEqual(['span5', 'span3', 'span2', 'span1']);
});

it('captures scopes on a root span before the spanStart event fires', () => {
let scopeAtSpanStart: Scope | undefined;
let isolationScopeAtSpanStart: Scope | undefined;
client.on('spanStart', span => {
scopeAtSpanStart = getCapturedScopesOnSpan(span).scope;
isolationScopeAtSpanStart = getCapturedScopesOnSpan(span).isolationScope;
});

startInactiveSpan({ name: 'root span' });

expect(scopeAtSpanStart).toBe(getCurrentScope());
expect(isolationScopeAtSpanStart).toBe(getIsolationScope());
});

it('captures scopes on a child span before the spanStart event fires', () => {
let scopeAtSpanStart: Scope | undefined;
let isolationScopeAtSpanStart: Scope | undefined;
client.on('spanStart', span => {
scopeAtSpanStart = getCapturedScopesOnSpan(span).scope;
isolationScopeAtSpanStart = getCapturedScopesOnSpan(span).isolationScope;
});

startSpan({ name: 'parent span' }, () => {
startInactiveSpan({ name: 'child span' });

expect(scopeAtSpanStart).toBe(getCurrentScope());
expect(isolationScopeAtSpanStart).toBe(getIsolationScope());
});
});
});

describe('suppressTracing', () => {
Expand Down Expand Up @@ -2887,4 +2917,20 @@ describe('ignoreSpans (core path, streaming)', () => {
expect(span.spanContext().traceId).toBe(getCurrentScope().getPropagationContext().traceId);
expect(span.spanContext().traceId).toBe('abc');
});

it('captures scopes on an ignored streamed span so its DSC can be resolved from the scope', () => {
const options = getDefaultTestClientOptions({
tracesSampleRate: 1,
traceLifecycle: 'stream',
ignoreSpans: ['ignored'],
});
client = new TestClient(options);
setCurrentClient(client);
client.init();

const span = startInactiveSpan({ name: 'ignored' });

expect(getCapturedScopesOnSpan(span).scope).toBe(getCurrentScope());
expect(getCapturedScopesOnSpan(span).isolationScope).toBe(getIsolationScope());
});
});
Loading