@@ -171,21 +171,36 @@ const DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {
171
171
export const browserTracingIntegration = ( ( _options : Partial < BrowserTracingOptions > = { } ) => {
172
172
registerSpanErrorInstrumentation ( ) ;
173
173
174
- const options = {
174
+ const {
175
+ enableInp,
176
+ enableLongTask,
177
+ _experiments : { enableInteractions } ,
178
+ beforeStartSpan,
179
+ idleTimeout,
180
+ finalTimeout,
181
+ childSpanTimeout,
182
+ markBackgroundSpan,
183
+ traceFetch,
184
+ traceXHR,
185
+ shouldCreateSpanForRequest,
186
+ enableHTTPTimings,
187
+ instrumentPageLoad,
188
+ instrumentNavigation,
189
+ } = {
175
190
...DEFAULT_BROWSER_TRACING_OPTIONS ,
176
191
..._options ,
177
192
} ;
178
193
179
194
const _collectWebVitals = startTrackingWebVitals ( ) ;
180
195
181
- if ( options . enableInp ) {
196
+ if ( enableInp ) {
182
197
startTrackingINP ( ) ;
183
198
}
184
199
185
- if ( options . enableLongTask ) {
200
+ if ( enableLongTask ) {
186
201
startTrackingLongTasks ( ) ;
187
202
}
188
- if ( options . _experiments . enableInteractions ) {
203
+ if ( enableInteractions ) {
189
204
startTrackingInteractions ( ) ;
190
205
}
191
206
@@ -196,18 +211,17 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
196
211
197
212
/** Create routing idle transaction. */
198
213
function _createRouteSpan ( client : Client , startSpanOptions : StartSpanOptions ) : Span {
199
- const { beforeStartSpan, idleTimeout, finalTimeout, childSpanTimeout } = options ;
200
-
201
214
const isPageloadTransaction = startSpanOptions . op === 'pageload' ;
202
215
203
216
const finalStartSpanOptions : StartSpanOptions = beforeStartSpan
204
217
? beforeStartSpan ( startSpanOptions )
205
218
: startSpanOptions ;
206
219
207
- // If `beforeStartSpan` set a custom name, record that fact
208
220
const attributes = finalStartSpanOptions . attributes || { } ;
209
221
210
- if ( finalStartSpanOptions . name !== finalStartSpanOptions . name ) {
222
+ // If `finalStartSpanOptions.name` is different than `startSpanOptions.name`
223
+ // it is because `beforeStartSpan` set a custom name. Therefore we set the source to 'custom'.
224
+ if ( startSpanOptions . name !== finalStartSpanOptions . name ) {
211
225
attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] = 'custom' ;
212
226
finalStartSpanOptions . attributes = attributes ;
213
227
}
@@ -227,16 +241,18 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
227
241
} ,
228
242
} ) ;
229
243
244
+ function emitFinish ( ) : void {
245
+ if ( [ 'interactive' , 'complete' ] . includes ( WINDOW . document . readyState ) ) {
246
+ client . emit ( 'idleSpanEnableAutoFinish' , idleSpan ) ;
247
+ }
248
+ }
249
+
230
250
if ( isPageloadTransaction && WINDOW . document ) {
231
251
WINDOW . document . addEventListener ( 'readystatechange' , ( ) => {
232
- if ( [ 'interactive' , 'complete' ] . includes ( WINDOW . document . readyState ) ) {
233
- client . emit ( 'idleSpanEnableAutoFinish' , idleSpan ) ;
234
- }
252
+ emitFinish ( ) ;
235
253
} ) ;
236
254
237
- if ( [ 'interactive' , 'complete' ] . includes ( WINDOW . document . readyState ) ) {
238
- client . emit ( 'idleSpanEnableAutoFinish' , idleSpan ) ;
239
- }
255
+ emitFinish ( ) ;
240
256
}
241
257
242
258
return idleSpan ;
@@ -245,9 +261,6 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
245
261
return {
246
262
name : BROWSER_TRACING_INTEGRATION_ID ,
247
263
afterAllSetup ( client ) {
248
- const { markBackgroundSpan, traceFetch, traceXHR, shouldCreateSpanForRequest, enableHTTPTimings, _experiments } =
249
- options ;
250
-
251
264
let activeSpan : Span | undefined ;
252
265
let startingUrl : string | undefined = WINDOW . location && WINDOW . location . href ;
253
266
@@ -304,65 +317,62 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
304
317
const scope = getCurrentScope ( ) ;
305
318
const oldPropagationContext = scope . getPropagationContext ( ) ;
306
319
307
- const newPropagationContext = {
320
+ scope . setPropagationContext ( {
308
321
...oldPropagationContext ,
309
322
sampled : oldPropagationContext . sampled !== undefined ? oldPropagationContext . sampled : spanIsSampled ( span ) ,
310
323
dsc : oldPropagationContext . dsc || getDynamicSamplingContextFromSpan ( span ) ,
311
- } ;
312
-
313
- scope . setPropagationContext ( newPropagationContext ) ;
324
+ } ) ;
314
325
} ) ;
315
326
316
- if ( options . instrumentPageLoad && WINDOW . location ) {
317
- const startSpanOptions : StartSpanOptions = {
318
- name : WINDOW . location . pathname ,
319
- // pageload should always start at timeOrigin (and needs to be in s, not ms)
320
- startTime : browserPerformanceTimeOrigin ? browserPerformanceTimeOrigin / 1000 : undefined ,
321
- attributes : {
322
- [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'url' ,
323
- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.pageload.browser ' ,
324
- } ,
325
- } ;
326
- startBrowserTracingPageLoadSpan ( client , startSpanOptions ) ;
327
- }
327
+ if ( WINDOW . location ) {
328
+ if ( instrumentPageLoad ) {
329
+ startBrowserTracingPageLoadSpan ( client , {
330
+ name : WINDOW . location . pathname ,
331
+ // pageload should always start at timeOrigin (and needs to be in s, not ms)
332
+ startTime : browserPerformanceTimeOrigin ? browserPerformanceTimeOrigin / 1000 : undefined ,
333
+ attributes : {
334
+ [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'url ' ,
335
+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.pageload.browser' ,
336
+ } ,
337
+ } ) ;
338
+ }
328
339
329
- if ( options . instrumentNavigation && WINDOW . location ) {
330
- addHistoryInstrumentationHandler ( ( { to, from } ) => {
331
- /**
332
- * This early return is there to account for some cases where a navigation transaction starts right after
333
- * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't
334
- * create an uneccessary navigation transaction.
335
- *
336
- * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also
337
- * only be caused in certain development environments where the usage of a hot module reloader is causing
338
- * errors.
339
- */
340
- if ( from === undefined && startingUrl && startingUrl . indexOf ( to ) !== - 1 ) {
341
- startingUrl = undefined ;
342
- return ;
343
- }
344
-
345
- if ( from !== to ) {
346
- startingUrl = undefined ;
347
- const startSpanOptions : StartSpanOptions = {
348
- name : WINDOW . location . pathname ,
349
- attributes : {
350
- [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'url' ,
351
- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.navigation.browser' ,
352
- } ,
353
- } ;
354
-
355
- startBrowserTracingNavigationSpan ( client , startSpanOptions ) ;
356
- }
357
- } ) ;
340
+ if ( instrumentNavigation ) {
341
+ addHistoryInstrumentationHandler ( ( { to, from } ) => {
342
+ /**
343
+ * This early return is there to account for some cases where a navigation transaction starts right after
344
+ * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't
345
+ * create an uneccessary navigation transaction.
346
+ *
347
+ * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also
348
+ * only be caused in certain development environments where the usage of a hot module reloader is causing
349
+ * errors.
350
+ */
351
+ if ( from === undefined && startingUrl && startingUrl . indexOf ( to ) !== - 1 ) {
352
+ startingUrl = undefined ;
353
+ return ;
354
+ }
355
+
356
+ if ( from !== to ) {
357
+ startingUrl = undefined ;
358
+ startBrowserTracingNavigationSpan ( client , {
359
+ name : WINDOW . location . pathname ,
360
+ attributes : {
361
+ [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'url' ,
362
+ [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.navigation.browser' ,
363
+ } ,
364
+ } ) ;
365
+ }
366
+ } ) ;
367
+ }
358
368
}
359
369
360
370
if ( markBackgroundSpan ) {
361
371
registerBackgroundTabDetection ( ) ;
362
372
}
363
373
364
- if ( _experiments . enableInteractions ) {
365
- registerInteractionListener ( options , latestRoute ) ;
374
+ if ( enableInteractions ) {
375
+ registerInteractionListener ( idleTimeout , finalTimeout , childSpanTimeout , latestRoute ) ;
366
376
}
367
377
368
378
instrumentOutgoingRequests ( {
@@ -402,14 +412,8 @@ export function startBrowserTracingPageLoadSpan(
402
412
* This will only do something if a browser tracing integration has been setup.
403
413
*/
404
414
export function startBrowserTracingNavigationSpan ( client : Client , spanOptions : StartSpanOptions ) : Span | undefined {
405
- getCurrentScope ( ) . setPropagationContext ( {
406
- traceId : uuid4 ( ) ,
407
- spanId : uuid4 ( ) . substring ( 16 ) ,
408
- } ) ;
409
- getIsolationScope ( ) . setPropagationContext ( {
410
- traceId : uuid4 ( ) ,
411
- spanId : uuid4 ( ) . substring ( 16 ) ,
412
- } ) ;
415
+ getCurrentScope ( ) . setPropagationContext ( generatePropagationContext ( ) ) ;
416
+ getIsolationScope ( ) . setPropagationContext ( generatePropagationContext ( ) ) ;
413
417
414
418
client . emit ( 'startNavigationSpan' , spanOptions ) ;
415
419
@@ -432,12 +436,13 @@ export function getMetaContent(metaName: string): string | undefined {
432
436
433
437
/** Start listener for interaction transactions */
434
438
function registerInteractionListener (
435
- options : BrowserTracingOptions ,
439
+ idleTimeout : BrowserTracingOptions [ 'idleTimeout' ] ,
440
+ finalTimeout : BrowserTracingOptions [ 'finalTimeout' ] ,
441
+ childSpanTimeout : BrowserTracingOptions [ 'childSpanTimeout' ] ,
436
442
latestRoute : { name : string | undefined ; source : TransactionSource | undefined } ,
437
443
) : void {
438
444
let inflightInteractionSpan : Span | undefined ;
439
445
const registerInteractionTransaction = ( ) : void => {
440
- const { idleTimeout, finalTimeout, childSpanTimeout } = options ;
441
446
const op = 'ui.action.click' ;
442
447
443
448
const activeSpan = getActiveSpan ( ) ;
@@ -478,9 +483,14 @@ function registerInteractionListener(
478
483
) ;
479
484
} ;
480
485
481
- [ 'click' ] . forEach ( type => {
482
- if ( WINDOW . document ) {
483
- addEventListener ( type , registerInteractionTransaction , { once : false , capture : true } ) ;
484
- }
485
- } ) ;
486
+ if ( WINDOW . document ) {
487
+ addEventListener ( 'click' , registerInteractionTransaction , { once : false , capture : true } ) ;
488
+ }
489
+ }
490
+
491
+ function generatePropagationContext ( ) : { traceId : string ; spanId : string } {
492
+ return {
493
+ traceId : uuid4 ( ) ,
494
+ spanId : uuid4 ( ) . substring ( 16 ) ,
495
+ } ;
486
496
}
0 commit comments