77 logger ,
88 safeJoin ,
99 supportsNativeFetch ,
10+ timestampWithMs ,
1011} from '@sentry/utils' ;
1112
1213import { Span as SpanClass } from '../span' ;
@@ -60,10 +61,8 @@ interface TracingOptions {
6061 startTransactionOnLocationChange : boolean ;
6162
6263 /**
63- * The maximum duration of a transaction before it will be discarded. This is for some edge cases where a browser
64- * completely freezes the JS state and picks it up later (background tabs).
65- * So after this duration, the SDK will not send the event.
66- * If you want to have an unlimited duration set it to 0.
64+ * The maximum duration of a transaction before it will be marked as "deadline_exceeded".
65+ * If you never want to mark a transaction set it to 0.
6766 * Time is in seconds.
6867 *
6968 * Default: 600
@@ -138,7 +137,7 @@ export class Tracing implements Integration {
138137
139138 public static _activities : { [ key : number ] : Activity } = { } ;
140139
141- private static _debounce : number = 0 ;
140+ private static _idleTransactionEndTimestamp : number = 0 ;
142141
143142 private readonly _emitOptionsWarning : boolean = false ;
144143
@@ -419,7 +418,7 @@ export class Tracing implements Integration {
419418 // b) A activity wasn't popped correctly and therefore the transaction is stalling
420419 Tracing . finishIdleTransaction ( ) ;
421420
422- Tracing . _log ( '[Tracing] startIdleTransaction, name:' , transactionContext . name ) ;
421+ Tracing . _log ( '[Tracing] startIdleTransaction' ) ;
423422
424423 const _getCurrentHub = Tracing . _getCurrentHub ;
425424 if ( ! _getCurrentHub ) {
@@ -453,7 +452,21 @@ export class Tracing implements Integration {
453452 const active = Tracing . _activeTransaction ;
454453 if ( active ) {
455454 Tracing . _addPerformanceEntries ( active ) ;
456- Tracing . _log ( '[Tracing] finishIdleTransaction' , active . name ) ;
455+ Tracing . _log ( '[Tracing] finishIdleTransaction' ) ;
456+
457+ if ( active . spanRecorder ) {
458+ const timeout = ( Tracing . options && Tracing . options . idleTimeout ) || 100 ;
459+ active . spanRecorder . spans = active . spanRecorder . spans . filter ( ( finishedSpan : Span ) => {
460+ const keepSpan = finishedSpan . startTimestamp < Tracing . _idleTransactionEndTimestamp + timeout ;
461+ if ( ! keepSpan ) {
462+ Tracing . _log (
463+ '[Tracing] discarding Span since it happened after Transaction was finished' ,
464+ finishedSpan . toJSON ( ) ,
465+ ) ;
466+ }
467+ return keepSpan ;
468+ } ) ;
469+ }
457470 active . finish ( ) ;
458471 Tracing . _resetActiveTransaction ( ) ;
459472 }
@@ -477,7 +490,7 @@ export class Tracing implements Integration {
477490 const timeOrigin = Tracing . _msToSec ( performance . timeOrigin ) ;
478491
479492 // tslint:disable-next-line: completed-docs
480- function addPerformanceNavigationTiming ( parent : SpanClass , entry : { [ key : string ] : number } , event : string ) : void {
493+ function addPerformanceNavigationTiming ( parent : Span , entry : { [ key : string ] : number } , event : string ) : void {
481494 const span = parent . startChild ( {
482495 description : event ,
483496 op : 'browser' ,
@@ -487,7 +500,7 @@ export class Tracing implements Integration {
487500 }
488501
489502 // tslint:disable-next-line: completed-docs
490- function addRequest ( parent : SpanClass , entry : { [ key : string ] : number } ) : void {
503+ function addRequest ( parent : Span , entry : { [ key : string ] : number } ) : void {
491504 const request = parent . startChild ( {
492505 description : 'request' ,
493506 op : 'browser' ,
@@ -560,7 +573,7 @@ export class Tracing implements Integration {
560573 if ( entry . initiatorType === 'xmlhttprequest' || entry . initiatorType === 'fetch' ) {
561574 // We need to update existing spans with new timing info
562575 if ( transactionSpan . spanRecorder ) {
563- transactionSpan . spanRecorder . spans . map ( ( finishedSpan : SpanClass ) => {
576+ transactionSpan . spanRecorder . spans . map ( ( finishedSpan : Span ) => {
564577 if ( finishedSpan . description && finishedSpan . description . indexOf ( resourceName ) !== - 1 ) {
565578 finishedSpan . startTimestamp = timeOrigin + startTime ;
566579 finishedSpan . endTimestamp = finishedSpan . startTimestamp + duration ;
@@ -669,9 +682,6 @@ export class Tracing implements Integration {
669682 return 0 ;
670683 }
671684
672- // We want to clear the timeout also here since we push a new activity
673- clearTimeout ( Tracing . _debounce ) ;
674-
675685 const _getCurrentHub = Tracing . _getCurrentHub ;
676686 if ( spanContext && _getCurrentHub ) {
677687 const hub = _getCurrentHub ( ) ;
@@ -740,16 +750,16 @@ export class Tracing implements Integration {
740750 }
741751
742752 const count = Object . keys ( Tracing . _activities ) . length ;
743- clearTimeout ( Tracing . _debounce ) ;
744753
745754 Tracing . _log ( '[Tracing] activies count' , count ) ;
746755
747756 if ( count === 0 && Tracing . _activeTransaction ) {
748757 const timeout = Tracing . options && Tracing . options . idleTimeout ;
749758 Tracing . _log ( `[Tracing] Flushing Transaction in ${ timeout } ms` ) ;
750- Tracing . _debounce = ( setTimeout ( ( ) => {
759+ Tracing . _idleTransactionEndTimestamp = timestampWithMs ( ) ;
760+ setTimeout ( ( ) => {
751761 Tracing . finishIdleTransaction ( ) ;
752- } , timeout ) as any ) as number ;
762+ } , timeout ) ;
753763 }
754764 }
755765}
0 commit comments