Skip to content

Commit c470dd3

Browse files
committed
ref(browser): Improve active span handling for browserTracingIntegration
1 parent 6779dfe commit c470dd3

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

packages/browser/src/tracing/browserTracingIntegration.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import {
1616
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
1717
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
1818
TRACING_DEFAULTS,
19+
addNonEnumerableProperty,
1920
browserPerformanceTimeOrigin,
2021
generateTraceId,
21-
getActiveSpan,
2222
getClient,
2323
getCurrentScope,
2424
getDynamicSamplingContextFromSpan,
@@ -246,7 +246,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
246246
};
247247

248248
/** Create routing idle transaction. */
249-
function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions): Span {
249+
function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions): void {
250250
const isPageloadTransaction = startSpanOptions.op === 'pageload';
251251

252252
const finalStartSpanOptions: StartSpanOptions = beforeStartSpan
@@ -274,8 +274,10 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
274274
beforeSpanEnd: span => {
275275
_collectWebVitals();
276276
addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans });
277+
setActiveIdleSpan(client, undefined);
277278
},
278279
});
280+
setActiveIdleSpan(client, idleSpan);
279281

280282
function emitFinish(): void {
281283
if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {
@@ -290,17 +292,16 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
290292

291293
emitFinish();
292294
}
293-
294-
return idleSpan;
295295
}
296296

297297
return {
298298
name: BROWSER_TRACING_INTEGRATION_ID,
299299
afterAllSetup(client) {
300-
let activeSpan: Span | undefined;
301300
let startingUrl: string | undefined = WINDOW.location && WINDOW.location.href;
302301

303302
function maybeEndActiveSpan(): void {
303+
const activeSpan = getActiveIdleSpan(client);
304+
304305
if (activeSpan && !spanToJSON(activeSpan).timestamp) {
305306
DEBUG_BUILD && logger.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);
306307
// If there's an open active span, we need to finish it before creating an new one.
@@ -315,7 +316,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
315316

316317
maybeEndActiveSpan();
317318

318-
activeSpan = _createRouteSpan(client, {
319+
_createRouteSpan(client, {
319320
op: 'navigation',
320321
...startSpanOptions,
321322
});
@@ -333,7 +334,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
333334
const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);
334335
getCurrentScope().setPropagationContext(propagationContext);
335336

336-
activeSpan = _createRouteSpan(client, {
337+
_createRouteSpan(client, {
337338
op: 'pageload',
338339
...startSpanOptions,
339340
});
@@ -408,7 +409,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
408409
}
409410

410411
if (enableInteractions) {
411-
registerInteractionListener(idleTimeout, finalTimeout, childSpanTimeout, latestRoute);
412+
registerInteractionListener(client, idleTimeout, finalTimeout, childSpanTimeout, latestRoute);
412413
}
413414

414415
if (enableInp) {
@@ -440,12 +441,9 @@ export function startBrowserTracingPageLoadSpan(
440441
traceOptions?: { sentryTrace?: string | undefined; baggage?: string | undefined },
441442
): Span | undefined {
442443
client.emit('startPageLoadSpan', spanOptions, traceOptions);
443-
444444
getCurrentScope().setTransactionName(spanOptions.name);
445445

446-
const span = getActiveSpan();
447-
const op = span && spanToJSON(span).op;
448-
return op === 'pageload' ? span : undefined;
446+
return getActiveIdleSpan(client);
449447
}
450448

451449
/**
@@ -460,9 +458,7 @@ export function startBrowserTracingNavigationSpan(client: Client, spanOptions: S
460458

461459
getCurrentScope().setTransactionName(spanOptions.name);
462460

463-
const span = getActiveSpan();
464-
const op = span && spanToJSON(span).op;
465-
return op === 'navigation' ? span : undefined;
461+
return getActiveIdleSpan(client);
466462
}
467463

468464
/** Returns the value of a meta tag */
@@ -479,6 +475,7 @@ export function getMetaContent(metaName: string): string | undefined {
479475

480476
/** Start listener for interaction transactions */
481477
function registerInteractionListener(
478+
client: Client,
482479
idleTimeout: BrowserTracingOptions['idleTimeout'],
483480
finalTimeout: BrowserTracingOptions['finalTimeout'],
484481
childSpanTimeout: BrowserTracingOptions['childSpanTimeout'],
@@ -494,10 +491,9 @@ function registerInteractionListener(
494491
const registerInteractionTransaction = (): void => {
495492
const op = 'ui.action.click';
496493

497-
const activeSpan = getActiveSpan();
498-
const rootSpan = activeSpan && getRootSpan(activeSpan);
499-
if (rootSpan) {
500-
const currentRootSpanOp = spanToJSON(rootSpan).op;
494+
const activeIdleSpan = getActiveIdleSpan(client);
495+
if (activeIdleSpan) {
496+
const currentRootSpanOp = spanToJSON(activeIdleSpan).op;
501497
if (['navigation', 'pageload'].includes(currentRootSpanOp as string)) {
502498
DEBUG_BUILD &&
503499
logger.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);
@@ -536,3 +532,13 @@ function registerInteractionListener(
536532
addEventListener('click', registerInteractionTransaction, { once: false, capture: true });
537533
}
538534
}
535+
536+
// We store the active idle span on the client object, so we can access it from exported functions
537+
const ACTIVE_IDLE_SPAN_PROPERTY = '_sentry_idleSpan';
538+
function getActiveIdleSpan(client: Client): Span | undefined {
539+
return (client as { [ACTIVE_IDLE_SPAN_PROPERTY]?: Span })[ACTIVE_IDLE_SPAN_PROPERTY];
540+
}
541+
542+
function setActiveIdleSpan(client: Client, span: Span | undefined): void {
543+
addNonEnumerableProperty(client, ACTIVE_IDLE_SPAN_PROPERTY, span);
544+
}

0 commit comments

Comments
 (0)