Skip to content

Commit dc7b16b

Browse files
committed
fix and test active span, span on scope
1 parent aabe208 commit dc7b16b

File tree

2 files changed

+109
-6
lines changed

2 files changed

+109
-6
lines changed

packages/core/src/tracing/trace.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ export function startSpan<T>(options: StartSpanOptions, callback: (span: Span) =
8888
scope,
8989
});
9090

91-
_setSpanForScope(scope, activeSpan);
91+
if (!_isIgnoredSpan(activeSpan)) {
92+
_setSpanForScope(scope, activeSpan);
93+
}
9294

9395
return handleCallbackErrors(
9496
() => callback(activeSpan),
@@ -154,7 +156,9 @@ export function startSpanManual<T>(options: StartSpanOptions, callback: (span: S
154156
scope,
155157
});
156158

157-
_setSpanForScope(scope, activeSpan);
159+
if (!_isIgnoredSpan(activeSpan)) {
160+
_setSpanForScope(scope, activeSpan);
161+
}
158162

159163
return handleCallbackErrors(
160164
// We pass the `finish` function to the callback, so the user can finish the span manually
@@ -206,7 +210,9 @@ export function startInactiveSpan(options: StartSpanOptions): Span {
206210

207211
const client = getClient();
208212
if (_shouldIgnoreStreamedSpan(client, spanArguments)) {
209-
return _createIgnoredSpan(client, parentSpan, scope);
213+
// purposefully not passing in the scope here because we don't want to set an
214+
// inactive span onto the scope (no exception for ignored spans)
215+
return _createIgnoredSpan(client, parentSpan);
210216
}
211217

212218
const shouldSkipSpan = options.onlyIfParent && !parentSpan;
@@ -606,15 +612,26 @@ function _shouldIgnoreStreamedSpan(client: Client | undefined, spanArguments: Se
606612
function _createIgnoredSpan(
607613
client: Client | undefined,
608614
parentSpan: SentrySpan | undefined,
609-
scope: Scope,
615+
scope?: Scope | undefined,
610616
): SentryNonRecordingSpan {
611617
client?.recordDroppedEvent('ignored', 'span');
612-
const nonRecordingSpan = new SentryNonRecordingSpan({ dropReason: 'ignored' });
613-
if (!parentSpan) {
618+
619+
const nonRecordingSpan = new SentryNonRecordingSpan({
620+
dropReason: 'ignored',
621+
// if there is a parent span, set the traceId of the parent span
622+
traceId: parentSpan?.spanContext().traceId,
623+
});
624+
625+
if (scope && !parentSpan) {
614626
// Put the ignored non-recording segment span onto the scope so that `getActiveSpan()` returns it
615627
// For child spans, we don't do this because there _is_ an active span on the scope. We can change
616628
// this if necessary.
617629
_setSpanForScope(scope, nonRecordingSpan);
618630
}
631+
619632
return nonRecordingSpan;
620633
}
634+
635+
function _isIgnoredSpan(span: Span): boolean {
636+
return span instanceof SentryNonRecordingSpan && span.dropReason === 'ignored';
637+
}

packages/core/test/lib/tracing/trace.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2653,4 +2653,90 @@ describe('ignoreSpans (core path, streaming)', () => {
26532653
expect(spyOnDroppedEvent).toHaveBeenCalledTimes(1);
26542654
expect(spyOnDroppedEvent).toHaveBeenCalledWith('ignored', 'span');
26552655
});
2656+
2657+
it('sets ignored segment span onto the scope', () => {
2658+
const options = getDefaultTestClientOptions({
2659+
tracesSampleRate: 1,
2660+
traceLifecycle: 'stream',
2661+
ignoreSpans: ['ignored'],
2662+
});
2663+
client = new TestClient(options);
2664+
setCurrentClient(client);
2665+
client.init();
2666+
2667+
startSpan({ name: 'ignored-segment' }, ignoredSegmentSpan => {
2668+
expect(ignoredSegmentSpan).toBeInstanceOf(SentryNonRecordingSpan);
2669+
expect(getActiveSpan()).toBe(ignoredSegmentSpan);
2670+
2671+
startSpan({ name: 'child' }, () => {
2672+
expect(getActiveSpan()).toBe(ignoredSegmentSpan);
2673+
});
2674+
});
2675+
});
2676+
2677+
it("doesn't set ignored child span onto the scope", () => {
2678+
const options = getDefaultTestClientOptions({
2679+
tracesSampleRate: 1,
2680+
traceLifecycle: 'stream',
2681+
ignoreSpans: ['ignored'],
2682+
});
2683+
client = new TestClient(options);
2684+
setCurrentClient(client);
2685+
client.init();
2686+
2687+
startSpan({ name: 'segment' }, segmentSpan => {
2688+
expect(getActiveSpan()).toBe(segmentSpan);
2689+
2690+
startSpan({ name: 'ignored-child' }, () => {
2691+
expect(getActiveSpan()).toBe(segmentSpan);
2692+
2693+
startSpan({ name: 'ignored-child-2' }, () => {
2694+
expect(getActiveSpan()).toBe(segmentSpan);
2695+
2696+
startSpan({ name: 'normal-child-2' }, normalChild2Span => {
2697+
expect(getActiveSpan()).toBe(normalChild2Span);
2698+
});
2699+
});
2700+
2701+
startSpan({ name: 'normal-child' }, normalChildSpan => {
2702+
expect(getActiveSpan()).toBe(normalChildSpan);
2703+
});
2704+
});
2705+
});
2706+
});
2707+
2708+
it("assigns the parent span's trace id to the ignored segment span", () => {
2709+
const options = getDefaultTestClientOptions({
2710+
tracesSampleRate: 1,
2711+
traceLifecycle: 'stream',
2712+
ignoreSpans: ['ignored'],
2713+
});
2714+
client = new TestClient(options);
2715+
setCurrentClient(client);
2716+
client.init();
2717+
2718+
startSpan({ name: 'ignored-segment' }, ignoredSegmentSpan => {
2719+
startSpan({ name: 'child' }, childSpan => {
2720+
expect(childSpan.spanContext().traceId).toBe(ignoredSegmentSpan.spanContext().traceId);
2721+
});
2722+
});
2723+
});
2724+
2725+
it("doesn't set inactive ignored segment spans onto the scope", () => {
2726+
const options = getDefaultTestClientOptions({
2727+
tracesSampleRate: 1,
2728+
traceLifecycle: 'stream',
2729+
ignoreSpans: ['ignored'],
2730+
});
2731+
client = new TestClient(options);
2732+
setCurrentClient(client);
2733+
client.init();
2734+
2735+
const span = startInactiveSpan({ name: 'ignored-segment' });
2736+
expect(getActiveSpan()).toBeUndefined();
2737+
2738+
span.end();
2739+
2740+
expect(getActiveSpan()).toBeUndefined();
2741+
});
26562742
});

0 commit comments

Comments
 (0)