1+ /* eslint-disable max-lines */
12import { Hub } from '@sentry/hub' ;
23import { TransactionContext } from '@sentry/types' ;
34import { getGlobalObject , logger , timestampWithMs } from '@sentry/utils' ;
@@ -7,6 +8,7 @@ import { Span, SpanRecorder } from './span';
78import { Transaction } from './transaction' ;
89
910export const DEFAULT_IDLE_TIMEOUT = 1000 ;
11+ export const DEFAULT_FINAL_TIMEOUT = 30000 ;
1012export const HEARTBEAT_INTERVAL = 5000 ;
1113
1214const global = getGlobalObject < Window > ( ) ;
@@ -73,18 +75,29 @@ export class IdleTransaction extends Transaction {
7375 * If a transaction is created and no activities are added, we want to make sure that
7476 * it times out properly. This is cleared and not used when activities are added.
7577 */
76- private _initTimeout : ReturnType < typeof global . setTimeout > | undefined ;
78+ private _idleTimeoutID : ReturnType < typeof global . setTimeout > | undefined ;
7779
7880 public constructor (
7981 transactionContext : TransactionContext ,
8082 private readonly _idleHub ?: Hub ,
8183 /**
8284 * The time to wait in ms until the idle transaction will be finished.
8385 * @default 1000
86+ *
87+ * TODO: Make _idleTimeout and _finalTimeout required to reduce duplication when setting the options
88+ * in `BrowserTracing`. This is considered a breaking change to the IdleTransaction API,
89+ * so we need to make sure we communicate it with react native.
8490 */
8591 private readonly _idleTimeout : number = DEFAULT_IDLE_TIMEOUT ,
8692 // Whether or not the transaction should put itself on the scope when it starts and pop itself off when it ends
8793 private readonly _onScope : boolean = false ,
94+ /**
95+ * The final value that a transaction cannot exceed
96+ * @default 15000
97+ * @experimental
98+ * @internal
99+ */
100+ private readonly _finalTimeout : number = DEFAULT_FINAL_TIMEOUT ,
88101 ) {
89102 super ( transactionContext , _idleHub ) ;
90103
@@ -98,11 +111,13 @@ export class IdleTransaction extends Transaction {
98111 _idleHub . configureScope ( scope => scope . setSpan ( this ) ) ;
99112 }
100113
101- this . _initTimeout = global . setTimeout ( ( ) => {
114+ this . _startIdleTimeout ( ) ;
115+ global . setTimeout ( ( ) => {
102116 if ( ! this . _finished ) {
117+ this . setTag ( FINISH_REASON_TAG , IDLE_TRANSACTION_FINISH_REASONS [ 3 ] ) ;
103118 this . finish ( ) ;
104119 }
105- } , this . _idleTimeout ) ;
120+ } , this . _finalTimeout ) ;
106121 }
107122
108123 /** {@inheritDoc } */
@@ -191,15 +206,35 @@ export class IdleTransaction extends Transaction {
191206 this . spanRecorder . add ( this ) ;
192207 }
193208
209+ /**
210+ * Creates an idletimeout
211+ */
212+ private _cancelIdleTimeout ( ) : void {
213+ if ( this . _idleTimeoutID ) {
214+ global . clearTimeout ( this . _idleTimeoutID ) ;
215+ this . _idleTimeoutID = undefined ;
216+ }
217+ }
218+
219+ /**
220+ * Creates an idletimeout
221+ */
222+ private _startIdleTimeout ( end ?: Parameters < IdleTransaction [ 'finish' ] > [ 0 ] ) : void {
223+ this . _cancelIdleTimeout ( ) ;
224+ this . _idleTimeoutID = global . setTimeout ( ( ) => {
225+ if ( ! this . _finished && Object . keys ( this . activities ) . length === 0 ) {
226+ this . setTag ( FINISH_REASON_TAG , IDLE_TRANSACTION_FINISH_REASONS [ 1 ] ) ;
227+ this . finish ( end ) ;
228+ }
229+ } , this . _idleTimeout ) ;
230+ }
231+
194232 /**
195233 * Start tracking a specific activity.
196234 * @param spanId The span id that represents the activity
197235 */
198236 private _pushActivity ( spanId : string ) : void {
199- if ( this . _initTimeout ) {
200- clearTimeout ( this . _initTimeout ) ;
201- this . _initTimeout = undefined ;
202- }
237+ this . _cancelIdleTimeout ( ) ;
203238 logger . log ( `[Tracing] pushActivity: ${ spanId } ` ) ;
204239 this . activities [ spanId ] = true ;
205240 logger . log ( '[Tracing] new activities count' , Object . keys ( this . activities ) . length ) ;
@@ -222,13 +257,7 @@ export class IdleTransaction extends Transaction {
222257 // We need to add the timeout here to have the real endtimestamp of the transaction
223258 // Remember timestampWithMs is in seconds, timeout is in ms
224259 const end = timestampWithMs ( ) + timeout / 1000 ;
225-
226- global . setTimeout ( ( ) => {
227- if ( ! this . _finished ) {
228- this . setTag ( FINISH_REASON_TAG , IDLE_TRANSACTION_FINISH_REASONS [ 1 ] ) ;
229- this . finish ( end ) ;
230- }
231- } , timeout ) ;
260+ this . _startIdleTimeout ( end ) ;
232261 }
233262 }
234263
0 commit comments