1
1
import { EventProcessor , Hub , Integration , Span , SpanContext , SpanStatus } from '@sentry/types' ;
2
- import {
3
- addInstrumentationHandler ,
4
- fill ,
5
- getGlobalObject ,
6
- isMatchingPattern ,
7
- logger ,
8
- supportsNativeFetch ,
9
- } from '@sentry/utils' ;
2
+ import { addInstrumentationHandler , getGlobalObject , isMatchingPattern , logger } from '@sentry/utils' ;
10
3
11
4
/**
12
5
* Options for Tracing integration
@@ -85,13 +78,6 @@ export class Tracing implements Integration {
85
78
*/
86
79
public static id : string = 'Tracing' ;
87
80
88
- /**
89
- * If we have an xhr we need to store the url in the instance.
90
- *
91
- */
92
- // @ts -ignore
93
- private _xhrUrl ?: string ;
94
-
95
81
/**
96
82
* Is Tracing enabled, this will be determined once per pageload.
97
83
*/
@@ -109,7 +95,7 @@ export class Tracing implements Integration {
109
95
110
96
private static _currentIndex : number = 0 ;
111
97
112
- private static readonly _activities : { [ key : number ] : Activity } = { } ;
98
+ public static readonly _activities : { [ key : number ] : Activity } = { } ;
113
99
114
100
private static _debounce : number = 0 ;
115
101
@@ -124,7 +110,10 @@ export class Tracing implements Integration {
124
110
idleTimeout : 500 ,
125
111
shouldCreateSpanForRequest ( url : string ) : boolean {
126
112
const origins = ( _options && _options . tracingOrigins ) || defaultTracingOrigins ;
127
- return origins . some ( ( origin : string | RegExp ) => isMatchingPattern ( url , origin ) ) ;
113
+ return (
114
+ origins . some ( ( origin : string | RegExp ) => isMatchingPattern ( url , origin ) ) &&
115
+ ! isMatchingPattern ( url , 'sentry_key' )
116
+ ) ;
128
117
} ,
129
118
startTransactionOnLocationChange : true ,
130
119
traceFetch : true ,
@@ -160,15 +149,13 @@ export class Tracing implements Integration {
160
149
callback : xhrCallback ,
161
150
type : 'xhr' ,
162
151
} ) ;
163
- this . _traceXHR ( getCurrentHub ) ;
164
152
}
165
153
// tslint:disable-next-line: no-non-null-assertion
166
154
if ( this . _options ! . traceFetch !== false ) {
167
155
addInstrumentationHandler ( {
168
156
callback : fetchCallback ,
169
157
type : 'fetch' ,
170
158
} ) ;
171
- this . _traceFetch ( getCurrentHub ) ;
172
159
}
173
160
174
161
// tslint:disable-next-line: no-non-null-assertion
@@ -188,120 +175,6 @@ export class Tracing implements Integration {
188
175
}
189
176
}
190
177
191
- /**
192
- * JSDoc
193
- */
194
- private _traceXHR ( getCurrentHub : ( ) => Hub ) : void {
195
- if ( ! ( 'XMLHttpRequest' in getGlobalObject < Window > ( ) ) ) {
196
- return ;
197
- }
198
-
199
- const xhrproto = XMLHttpRequest . prototype ;
200
-
201
- fill (
202
- xhrproto ,
203
- 'open' ,
204
- originalOpen =>
205
- function ( this : XMLHttpRequest , ...args : any [ ] ) : void {
206
- // @ts -ignore
207
- const self = getCurrentHub ( ) . getIntegration ( Tracing ) ;
208
- if ( self ) {
209
- self . _xhrUrl = args [ 1 ] as string ;
210
- }
211
- // tslint:disable-next-line: no-unsafe-any
212
- return originalOpen . apply ( this , args ) ;
213
- } ,
214
- ) ;
215
-
216
- fill (
217
- xhrproto ,
218
- 'send' ,
219
- originalSend =>
220
- function ( this : XMLHttpRequest , ...args : any [ ] ) : void {
221
- // @ts -ignore
222
- const self = getCurrentHub ( ) . getIntegration ( Tracing ) ;
223
- // tslint:disable-next-line: no-non-null-assertion
224
- if ( self && self . _xhrUrl && self . _options ! . tracingOrigins ) {
225
- const url = self . _xhrUrl ;
226
- const headers = getCurrentHub ( ) . traceHeaders ( ) ;
227
- // tslint:disable-next-line: prefer-for-of no-non-null-assertion
228
- let isWhitelisted = self . _options ! . tracingOrigins . some ( ( origin : string | RegExp ) =>
229
- isMatchingPattern ( url , origin ) ,
230
- ) ;
231
-
232
- if ( isMatchingPattern ( url , 'sentry_key' ) ) {
233
- // If sentry_key is in the url, it's an internal store request to sentry
234
- // we do not want to add the trace header to store requests
235
- isWhitelisted = false ;
236
- }
237
-
238
- if ( isWhitelisted && this . setRequestHeader ) {
239
- Object . keys ( headers ) . forEach ( key => {
240
- this . setRequestHeader ( key , headers [ key ] ) ;
241
- } ) ;
242
- }
243
- }
244
- // tslint:disable-next-line: no-unsafe-any
245
- return originalSend . apply ( this , args ) ;
246
- } ,
247
- ) ;
248
- }
249
-
250
- /**
251
- * JSDoc
252
- */
253
- private _traceFetch ( getCurrentHub : ( ) => Hub ) : void {
254
- if ( ! supportsNativeFetch ( ) ) {
255
- return ;
256
- }
257
-
258
- // tslint:disable: only-arrow-functions
259
- fill ( getGlobalObject < Window > ( ) , 'fetch' , function ( originalFetch : ( ) => void ) : ( ) => void {
260
- return function ( ...args : any [ ] ) : void {
261
- // @ts -ignore
262
- const hub = getCurrentHub ( ) ;
263
- const self = hub . getIntegration ( Tracing ) ;
264
- // tslint:disable-next-line: no-non-null-assertion
265
- if ( self && self . _options ! . tracingOrigins ) {
266
- const url = args [ 0 ] as string ;
267
- const options = ( args [ 1 ] = ( args [ 1 ] as { [ key : string ] : any } ) || { } ) ;
268
-
269
- let isWhitelisted = false ;
270
- // tslint:disable-next-line: no-non-null-assertion
271
- self . _options ! . tracingOrigins . forEach ( ( whiteListUrl : string | RegExp ) => {
272
- if ( ! isWhitelisted ) {
273
- isWhitelisted = isMatchingPattern ( url , whiteListUrl ) ;
274
- }
275
- } ) ;
276
-
277
- if ( isMatchingPattern ( url , 'sentry_key' ) ) {
278
- // If sentry_key is in the url, it's an internal store request to sentry
279
- // we do not want to add the trace header to store requests
280
- isWhitelisted = false ;
281
- }
282
-
283
- if ( isWhitelisted ) {
284
- if ( options . headers ) {
285
- if ( Array . isArray ( options . headers ) ) {
286
- options . headers = [ ...options . headers , ...Object . entries ( hub . traceHeaders ( ) ) ] ;
287
- } else {
288
- options . headers = {
289
- ...options . headers ,
290
- ...hub . traceHeaders ( ) ,
291
- } ;
292
- }
293
- } else {
294
- options . headers = hub . traceHeaders ( ) ;
295
- }
296
- }
297
- }
298
- // tslint:disable-next-line: no-unsafe-any
299
- return originalFetch . apply ( getGlobalObject < Window > ( ) , args ) ;
300
- } ;
301
- } ) ;
302
- // tslint:enable: only-arrow-functions
303
- }
304
-
305
178
/**
306
179
* Is tracing enabled
307
180
*/
@@ -508,6 +381,15 @@ function xhrCallback(handlerData: { [key: string]: any }): void {
508
381
description : `${ xhr . method } ${ xhr . url } ` ,
509
382
op : 'http' ,
510
383
} ) ;
384
+
385
+ // Adding the trace header to the span
386
+ const activity = Tracing . _activities [ handlerData . xhr . __sentry_xhr_activity_id__ ] ;
387
+ if ( activity ) {
388
+ const span = activity . span ;
389
+ if ( span && handlerData . xhr . setRequestHeader ) {
390
+ handlerData . xhr . setRequestHeader ( 'sentry-trace' , span . toTraceparent ( ) ) ;
391
+ }
392
+ }
511
393
// tslint:enable: no-unsafe-any
512
394
}
513
395
@@ -520,22 +402,42 @@ function fetchCallback(handlerData: { [key: string]: any }): void {
520
402
return ;
521
403
}
522
404
523
- if ( handlerData . endTimestamp && handlerData . __activity ) {
524
- Tracing . popActivity ( handlerData . __activity , handlerData . fetchData ) ;
405
+ if ( ! Tracing . options . shouldCreateSpanForRequest ( handlerData . fetchData . url ) ) {
406
+ return ;
407
+ }
408
+
409
+ if ( handlerData . endTimestamp && handlerData . fetchData . __activity ) {
410
+ Tracing . popActivity ( handlerData . fetchData . __activity , handlerData . fetchData ) ;
525
411
} else {
526
- handlerData . __activity = Tracing . pushActivity ( 'fetch' , {
412
+ handlerData . fetchData . __activity = Tracing . pushActivity ( 'fetch' , {
527
413
data : {
528
414
...handlerData . fetchData ,
529
415
type : 'fetch' ,
530
416
} ,
531
417
description : `${ handlerData . fetchData . method } ${ handlerData . fetchData . url } ` ,
532
418
op : 'http' ,
533
419
} ) ;
534
- }
535
420
536
- // if (handlerData.error) {
537
- // } else {
538
- // }
421
+ const activity = Tracing . _activities [ handlerData . fetchData . __activity ] ;
422
+ if ( activity ) {
423
+ const span = activity . span ;
424
+ if ( span ) {
425
+ const options = ( handlerData . args [ 1 ] = ( handlerData . args [ 1 ] as { [ key : string ] : any } ) || { } ) ;
426
+ if ( options . headers ) {
427
+ if ( Array . isArray ( options . headers ) ) {
428
+ options . headers = [ ...options . headers , { 'sentry-trace' : span . toTraceparent ( ) } ] ;
429
+ } else {
430
+ options . headers = {
431
+ ...options . headers ,
432
+ 'sentry-trace' : span . toTraceparent ( ) ,
433
+ } ;
434
+ }
435
+ } else {
436
+ options . headers = { 'sentry-trace' : span . toTraceparent ( ) } ;
437
+ }
438
+ }
439
+ }
440
+ }
539
441
// tslint:enable: no-unsafe-any
540
442
}
541
443
0 commit comments