@@ -74,6 +74,16 @@ interface TracingOptions {
7474 * Default: 600
7575 */
7676 maxTransactionDuration : number ;
77+
78+ /**
79+ * Flag to discard all spans that occur in background. This includes transactions. Browser background tab timing is
80+ * not suited towards doing precise measurements of operations. That's why this option discards any active transaction
81+ * and also doesn't add any spans that happen in the background. Background spans/transaction can mess up your
82+ * statistics in non deterministic ways that's why we by default recommend leaving this opition enabled.
83+ *
84+ * Default: true
85+ */
86+ discardBackgroundSpans : boolean ;
7787}
7888
7989/** JSDoc */
@@ -114,9 +124,9 @@ export class Tracing implements Integration {
114124
115125 private static _activeTransaction ?: Span ;
116126
117- private static _currentIndex : number = 0 ;
127+ private static _currentIndex : number = 1 ;
118128
119- public static readonly _activities : { [ key : number ] : Activity } = { } ;
129+ public static _activities : { [ key : number ] : Activity } = { } ;
120130
121131 private static _debounce : number = 0 ;
122132
@@ -127,8 +137,9 @@ export class Tracing implements Integration {
127137 *
128138 * @param _options TracingOptions
129139 */
130- public constructor ( private readonly _options ?: Partial < TracingOptions > ) {
140+ public constructor ( _options ?: Partial < TracingOptions > ) {
131141 const defaults = {
142+ discardBackgroundSpans : true ,
132143 idleTimeout : 500 ,
133144 maxTransactionDuration : 600 ,
134145 shouldCreateSpanForRequest ( url : string ) : boolean {
@@ -148,7 +159,7 @@ export class Tracing implements Integration {
148159 if ( ! _options || ! Array . isArray ( _options . tracingOrigins ) || _options . tracingOrigins . length === 0 ) {
149160 this . _emitOptionsWarning = true ;
150161 }
151- Tracing . options = this . _options = {
162+ Tracing . options = {
152163 ...defaults ,
153164 ..._options ,
154165 } ;
@@ -171,23 +182,21 @@ export class Tracing implements Integration {
171182 return ;
172183 }
173184
174- // tslint:disable-next-line: no-non-null-assertion
175- if ( this . _options ! . traceXHR !== false ) {
185+ if ( Tracing . options . traceXHR ) {
176186 addInstrumentationHandler ( {
177187 callback : xhrCallback ,
178188 type : 'xhr' ,
179189 } ) ;
180190 }
181- // tslint:disable-next-line: no-non-null-assertion
182- if ( this . _options ! . traceFetch !== false && supportsNativeFetch ( ) ) {
191+
192+ if ( Tracing . options . traceFetch && supportsNativeFetch ( ) ) {
183193 addInstrumentationHandler ( {
184194 callback : fetchCallback ,
185195 type : 'fetch' ,
186196 } ) ;
187197 }
188198
189- // tslint:disable-next-line: no-non-null-assertion
190- if ( this . _options ! . startTransactionOnLocationChange ) {
199+ if ( Tracing . options . startTransactionOnLocationChange ) {
191200 addInstrumentationHandler ( {
192201 callback : historyCallback ,
193202 type : 'history' ,
@@ -202,6 +211,16 @@ export class Tracing implements Integration {
202211 } ) ;
203212 }
204213
214+ if ( Tracing . options . discardBackgroundSpans && global . document ) {
215+ document . addEventListener ( 'visibilitychange' , ( ) => {
216+ if ( document . hidden && Tracing . _activeTransaction ) {
217+ logger . log ( '[Tracing] Discarded active transaction incl. activities since tab moved to the background' ) ;
218+ Tracing . _activeTransaction = undefined ;
219+ Tracing . _activities = { } ;
220+ }
221+ } ) ;
222+ }
223+
205224 // This EventProcessor makes sure that the transaction is not longer than maxTransactionDuration
206225 addGlobalEventProcessor ( ( event : Event ) => {
207226 const self = getCurrentHub ( ) . getIntegration ( Tracing ) ;
@@ -351,6 +370,10 @@ export class Tracing implements Integration {
351370 // Tracing is not enabled
352371 return 0 ;
353372 }
373+ if ( ! Tracing . _activeTransaction ) {
374+ logger . log ( `[Tracing] Not pushing activity ${ name } since there is no active transaction` ) ;
375+ return 0 ;
376+ }
354377
355378 // We want to clear the timeout also here since we push a new activity
356379 clearTimeout ( Tracing . _debounce ) ;
@@ -389,7 +412,10 @@ export class Tracing implements Integration {
389412 * Removes activity and finishes the span in case there is one
390413 */
391414 public static popActivity ( id : number , spanData ?: { [ key : string ] : any } ) : void {
392- if ( ! Tracing . _isEnabled ( ) ) {
415+ // The !id is on purpose to also fail with 0
416+ // Since 0 is returned by push activity in case tracing is not enabled
417+ // or there is no active transaction
418+ if ( ! Tracing . _isEnabled ( ) || ! id ) {
393419 // Tracing is not enabled
394420 return ;
395421 }
@@ -422,7 +448,7 @@ export class Tracing implements Integration {
422448
423449 logger . log ( '[Tracing] activies count' , count ) ;
424450
425- if ( count === 0 ) {
451+ if ( count === 0 && Tracing . _activeTransaction ) {
426452 const timeout = Tracing . options && Tracing . options . idleTimeout ;
427453 logger . log ( `[Tracing] Flushing Transaction in ${ timeout } ms` ) ;
428454 Tracing . _debounce = ( setTimeout ( ( ) => {
0 commit comments