Skip to content
Merged
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
68 changes: 37 additions & 31 deletions packages/core/src/tracing/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,22 +88,13 @@ export function startSpan<T>(options: StartSpanOptions, callback: (span: Span) =
// Ignored root spans still need to be set on scope so that `getActiveSpan()` returns them
// and descendants are also non-recording. Ignored child spans don't need this because
// the parent span is already on scope.
if (!spanIsIgnored(activeSpan) || !parentSpan) {
_setSpanForScope(scope, activeSpan);
}
const makeSpanActive = !spanIsIgnored(activeSpan) || !parentSpan;

return handleCallbackErrors(
return runCallback(
activeSpan,
makeSpanActive,
() => callback(activeSpan),
() => {
// Only update the span status if it hasn't been changed yet, and the span is not yet finished
const { status } = spanToJSON(activeSpan);
if (activeSpan.isRecording() && status === 'ok') {
activeSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
}
},
() => {
activeSpan.end();
},
() => activeSpan.end(),
);
});
});
Expand Down Expand Up @@ -150,24 +141,13 @@ export function startSpanManual<T>(options: StartSpanOptions, callback: (span: S

// We don't set ignored child spans onto the scope because there likely is an active,
// unignored span on the scope already.
if (!spanIsIgnored(activeSpan) || !parentSpan) {
_setSpanForScope(scope, activeSpan);
}
const makeSpanActive = !spanIsIgnored(activeSpan) || !parentSpan;

return handleCallbackErrors(
// We pass the `finish` function to the callback, so the user can finish the span manually
// this is mainly here for historic purposes because previously, we instructed users to call
// `finish` instead of `span.end()` to also clean up the scope. Nowadays, calling `span.end()`
// or `finish` has the same effect and we simply leave it here to avoid breaking user code.
() => callback(activeSpan, () => activeSpan.end()),
() => {
// Only update the span status if it hasn't been changed yet, and the span is not yet finished
const { status } = spanToJSON(activeSpan);
if (activeSpan.isRecording() && status === 'ok') {
activeSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
}
},
);
// We pass the `finish` function to the callback, so the user can finish the span manually
// this is mainly here for historic purposes because previously, we instructed users to call
// `finish` instead of `span.end()` to also clean up the scope. Nowadays, calling `span.end()`
// or `finish` has the same effect and we simply leave it here to avoid breaking user code.
return runCallback(activeSpan, makeSpanActive, () => callback(activeSpan, () => activeSpan.end()));
});
});
}
Expand Down Expand Up @@ -677,3 +657,29 @@ function _shouldIgnoreStreamedSpan(client: Client | undefined, spanArguments: Se
export function spanIsIgnored(span: Span): span is SentryNonRecordingSpan {
return spanIsNonRecordingSpan(span) && span.dropReason === 'ignored';
}

function runCallback<T>(span: Span, makeSpanActive: boolean, callback: () => T, finallyCallback?: () => void): T {
const wrapper = makeSpanActive
? (callback: () => T) => {
return withActiveSpan(span, () => {
// Make sure the correct scope is captured on the span, since withActiveSpan forks the scope
setCapturedScopesOnSpan(span, getCurrentScope(), getIsolationScope());

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@andreiborza had to add this too to make tests pass, maybe this was part of the problem you ran into before with tags/scopes not matching properly 🤔

return callback();
});
}
: (callback: () => T) => callback();

return wrapper(() =>
handleCallbackErrors(
() => callback(),
() => {
// Only update the span status if it hasn't been changed yet, and the span is not yet finished
const { status } = spanToJSON(span);
if (span.isRecording() && status === 'ok') {
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
}
},
finallyCallback,
),
);
}
Comment thread
cursor[bot] marked this conversation as resolved.
Loading