1
1
// tslint:disable:max-classes-per-file
2
2
import { Hub } from '@sentry/hub' ;
3
3
import { TransactionContext } from '@sentry/types' ;
4
- import { timestampWithMs , logger } from '@sentry/utils' ;
4
+ import { logger , timestampWithMs } from '@sentry/utils' ;
5
5
6
6
import { Span } from './span' ;
7
7
import { SpanStatus } from './spanstatus' ;
8
8
import { SpanRecorder , Transaction } from './transaction' ;
9
- import { BrowserTracing } from './integrations/browsertracing' ;
10
9
11
10
/**
12
11
* @inheritDoc
13
12
*/
14
- class IdleTransactionSpanRecorder extends SpanRecorder {
13
+ export class IdleTransactionSpanRecorder extends SpanRecorder {
15
14
private readonly _pushActivity ?: ( id : string ) => void ;
16
15
private readonly _popActivity ?: ( id : string ) => void ;
17
16
@@ -25,8 +24,10 @@ class IdleTransactionSpanRecorder extends SpanRecorder {
25
24
* @inheritDoc
26
25
*/
27
26
public add ( span : Span ) : void {
27
+ // tslint:disable-next-line: no-unbound-method
28
+ const oldFinish : Function = span . finish ;
28
29
span . finish = ( endTimestamp ?: number ) => {
29
- span . finish ( endTimestamp ) ;
30
+ oldFinish ( endTimestamp ) ;
30
31
if ( this . _popActivity ) {
31
32
this . _popActivity ( span . spanId ) ;
32
33
}
@@ -47,7 +48,7 @@ export class IdleTransaction extends Transaction {
47
48
/**
48
49
* Activities store a list of active spans
49
50
*/
50
- public _activities : Record < string , boolean > = { } ;
51
+ public activities : Record < string , boolean > = { } ;
51
52
52
53
private _heartbeatTimer : number = 0 ;
53
54
@@ -64,32 +65,34 @@ export class IdleTransaction extends Transaction {
64
65
}
65
66
66
67
/**
67
- * Checks when entries of this._activities are not changing for 3 beats.
68
+ * Checks when entries of this.activities are not changing for 3 beats.
68
69
* If this occurs we finish the transaction.
69
70
*/
70
71
private _beat ( ) : void {
71
72
clearTimeout ( this . _heartbeatTimer ) ;
72
- const keys = Object . keys ( this . _activities ) ;
73
- if ( keys . length ) {
74
- const heartbeatString = keys . reduce ( ( prev : string , current : string ) => prev + current ) ;
75
- if ( heartbeatString === this . _prevHeartbeatString ) {
76
- this . _heartbeatCounter ++ ;
77
- } else {
78
- this . _heartbeatCounter = 0 ;
79
- }
80
- if ( this . _heartbeatCounter >= 3 ) {
81
- logger . log (
82
- `[Tracing] Transaction: ${
83
- SpanStatus . Cancelled
84
- } -> Heartbeat safeguard kicked in since content hasn't changed for 3 beats`,
85
- ) ;
86
- this . setStatus ( SpanStatus . DeadlineExceeded ) ;
87
- this . setTag ( 'heartbeat' , 'failed' ) ;
88
- this . _finishIdleTransaction ( timestampWithMs ( ) ) ;
89
- }
90
- this . _prevHeartbeatString = heartbeatString ;
73
+ const keys = Object . keys ( this . activities ) ;
74
+ const heartbeatString = keys . length ? keys . reduce ( ( prev : string , current : string ) => prev + current ) : '' ;
75
+
76
+ if ( heartbeatString === this . _prevHeartbeatString ) {
77
+ this . _heartbeatCounter ++ ;
78
+ } else {
79
+ this . _heartbeatCounter = 1 ;
80
+ }
81
+
82
+ this . _prevHeartbeatString = heartbeatString ;
83
+
84
+ if ( this . _heartbeatCounter >= 3 ) {
85
+ logger . log (
86
+ `[Tracing] Transaction: ${
87
+ SpanStatus . Cancelled
88
+ } -> Heartbeat safeguard kicked in since content hasn't changed for 3 beats`,
89
+ ) ;
90
+ this . setStatus ( SpanStatus . DeadlineExceeded ) ;
91
+ this . setTag ( 'heartbeat' , 'failed' ) ;
92
+ this . _finishIdleTransaction ( timestampWithMs ( ) ) ;
93
+ } else {
94
+ this . _pingHeartbeat ( ) ;
91
95
}
92
- this . _pingHeartbeat ( ) ;
93
96
}
94
97
95
98
/**
@@ -131,6 +134,7 @@ export class IdleTransaction extends Transaction {
131
134
132
135
logger . log ( '[Tracing] flushing IdleTransaction' ) ;
133
136
this . finish ( ) ;
137
+ this . _finished = true ;
134
138
} else {
135
139
logger . log ( '[Tracing] No active IdleTransaction' ) ;
136
140
}
@@ -141,20 +145,20 @@ export class IdleTransaction extends Transaction {
141
145
* @param spanId The span id that represents the activity
142
146
*/
143
147
private _pushActivity ( spanId : string ) : void {
144
- this . _activities [ spanId ] = true ;
148
+ this . activities [ spanId ] = true ;
145
149
}
146
150
147
151
/**
148
152
* Remove an activity from usage
149
153
* @param spanId The span id that represents the activity
150
154
*/
151
155
private _popActivity ( spanId : string ) : void {
152
- if ( this . _activities [ spanId ] ) {
156
+ if ( this . activities [ spanId ] ) {
153
157
// tslint:disable-next-line: no-dynamic-delete
154
- delete this . _activities [ spanId ] ;
158
+ delete this . activities [ spanId ] ;
155
159
}
156
160
157
- const count = Object . keys ( this . _activities ) . length ;
161
+ const count = Object . keys ( this . activities ) . length ;
158
162
if ( count === 0 ) {
159
163
const timeout = this . _idleTimeout ;
160
164
// We need to add the timeout here to have the real endtimestamp of the transaction
@@ -171,8 +175,18 @@ export class IdleTransaction extends Transaction {
171
175
*/
172
176
public initSpanRecorder ( maxlen ?: number ) : void {
173
177
if ( ! this . spanRecorder ) {
178
+ const pushActivity = ( id : string ) => {
179
+ if ( id !== this . spanId ) {
180
+ this . _pushActivity ( id ) ;
181
+ }
182
+ } ;
183
+ const popActivity = ( id : string ) => {
184
+ if ( id !== this . spanId ) {
185
+ this . _popActivity ( id ) ;
186
+ }
187
+ } ;
174
188
// tslint:disable-next-line: no-unbound-method
175
- this . spanRecorder = new IdleTransactionSpanRecorder ( maxlen , this . _popActivity , this . _pushActivity ) ;
189
+ this . spanRecorder = new IdleTransactionSpanRecorder ( maxlen , pushActivity , popActivity ) ;
176
190
}
177
191
this . spanRecorder . add ( this ) ;
178
192
}
0 commit comments