MCPcopy Create free account
hub / github.com/getsentry/sentry-javascript / startSpanManual

Function startSpanManual

packages/core/src/tracing/trace.ts:116–167  ·  view source on GitHub ↗
(options: StartSpanOptions, callback: (span: Span, finish: () => void) => T)

Source from the content-addressed store, hash-verified

114 * it may just be a non-recording span if the span is not sampled or if tracing is disabled.
115 */
116export function startSpanManual<T>(options: StartSpanOptions, callback: (span: Span, finish: () => void) => T): T {
117 const acs = getAcs();
118 if (acs.startSpanManual) {
119 return acs.startSpanManual(options, callback);
120 }
121
122 const spanArguments = parseSentrySpanArguments(options);
123 const { forceTransaction, parentSpan: customParentSpan, scope: customScope } = options;
124
125 const customForkedScope = customScope?.clone();
126
127 return withScope(customForkedScope, () => {
128 // If `options.parentSpan` is defined, we want to wrap the callback in `withActiveSpan`
129 const wrapper = getActiveSpanWrapper<T>(customParentSpan);
130
131 return wrapper(() => {
132 const scope = getCurrentScope();
133 const parentSpan = getParentSpan(scope, customParentSpan);
134
135 const missingRequiredParent = options.onlyIfParent && !parentSpan;
136 const activeSpan = missingRequiredParent
137 ? startMissingRequiredParentSpan(scope, getClient())
138 : createChildOrRootSpan({
139 parentSpan,
140 spanArguments,
141 forceTransaction,
142 scope,
143 });
144
145 // We don't set ignored child spans onto the scope because there likely is an active,
146 // unignored span on the scope already.
147 if (!_isIgnoredSpan(activeSpan) || !parentSpan) {
148 _setSpanForScope(scope, activeSpan);
149 }
150
151 return handleCallbackErrors(
152 // We pass the `finish` function to the callback, so the user can finish the span manually
153 // this is mainly here for historic purposes because previously, we instructed users to call
154 // `finish` instead of `span.end()` to also clean up the scope. Nowadays, calling `span.end()`
155 // or `finish` has the same effect and we simply leave it here to avoid breaking user code.
156 () => callback(activeSpan, () => activeSpan.end()),
157 () => {
158 // Only update the span status if it hasn't been changed yet, and the span is not yet finished
159 const { status } = spanToJSON(activeSpan);
160 if (activeSpan.isRecording() && (!status || status === 'ok')) {
161 activeSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
162 }
163 },
164 );
165 });
166 });
167}
168
169/**
170 * Creates a span. This span is not set as active, so will not get automatic instrumentation spans

Callers 15

withElysiaFunction · 0.90
trace.test.tsFile · 0.90
idleSpan.test.tsFile · 0.90
trpcMiddlewareFunction · 0.90
wrappedHandleFunction · 0.90
createSpanFunction · 0.90
layerHandlePatchedFunction · 0.90
applyFunction · 0.90
handleLLMStartFunction · 0.90
handleChatModelStartFunction · 0.90
handleChainStartFunction · 0.90
handleToolStartFunction · 0.90

Calls 15

withScopeFunction · 0.90
getCurrentScopeFunction · 0.90
getClientFunction · 0.90
_setSpanForScopeFunction · 0.90
handleCallbackErrorsFunction · 0.90
spanToJSONFunction · 0.90
getAcsFunction · 0.85
parseSentrySpanArgumentsFunction · 0.85
wrapperFunction · 0.85
getParentSpanFunction · 0.85
createChildOrRootSpanFunction · 0.85

Tested by

no test coverage detected