1
1
import { instrumentFetchRequest } from '@sentry-internal/tracing' ;
2
- import { addBreadcrumb , getClient , isSentryRequestUrl } from '@sentry/core' ;
3
- import type { FetchBreadcrumbData , FetchBreadcrumbHint , HandlerDataFetch , Integration , Span } from '@sentry/types' ;
2
+ import {
3
+ addBreadcrumb ,
4
+ convertIntegrationFnToClass ,
5
+ defineIntegration ,
6
+ getClient ,
7
+ isSentryRequestUrl ,
8
+ } from '@sentry/core' ;
9
+ import type {
10
+ Client ,
11
+ FetchBreadcrumbData ,
12
+ FetchBreadcrumbHint ,
13
+ HandlerDataFetch ,
14
+ Integration ,
15
+ IntegrationClass ,
16
+ IntegrationFn ,
17
+ Span ,
18
+ } from '@sentry/types' ;
4
19
import { LRUMap , addFetchInstrumentationHandler , stringMatchesSomePattern } from '@sentry/utils' ;
5
20
21
+ const INTEGRATION_NAME = 'WinterCGFetch' ;
22
+
23
+ const HAS_CLIENT_MAP = new WeakMap < Client , boolean > ( ) ;
24
+
6
25
export interface Options {
7
26
/**
8
27
* Whether breadcrumbs should be recorded for requests
9
28
* Defaults to true
10
29
*/
11
30
breadcrumbs : boolean ;
31
+
12
32
/**
13
33
* Function determining whether or not to create spans to track outgoing requests to the given URL.
14
34
* By default, spans will be created for all outgoing requests.
15
35
*/
16
36
shouldCreateSpanForRequest ?: ( url : string ) => boolean ;
17
37
}
18
38
19
- /**
20
- * Creates spans and attaches tracing headers to fetch requests on WinterCG runtimes.
21
- */
22
- export class WinterCGFetch implements Integration {
23
- /**
24
- * @inheritDoc
25
- */
26
- public static id : string = 'WinterCGFetch' ;
27
-
28
- /**
29
- * @inheritDoc
30
- */
31
- public name : string = WinterCGFetch . id ;
32
-
33
- private readonly _options : Options ;
39
+ const _winterCGFetch = ( ( options : Partial < Options > = { } ) => {
40
+ const breadcrumbs = options . breadcrumbs === undefined ? true : options . breadcrumbs ;
41
+ const shouldCreateSpanForRequest = options . shouldCreateSpanForRequest ;
34
42
35
- private readonly _createSpanUrlMap : LRUMap < string , boolean > = new LRUMap ( 100 ) ;
36
- private readonly _headersUrlMap : LRUMap < string , boolean > = new LRUMap ( 100 ) ;
43
+ const _createSpanUrlMap = new LRUMap < string , boolean > ( 100 ) ;
44
+ const _headersUrlMap = new LRUMap < string , boolean > ( 100 ) ;
37
45
38
- public constructor ( _options : Partial < Options > = { } ) {
39
- this . _options = {
40
- breadcrumbs : _options . breadcrumbs === undefined ? true : _options . breadcrumbs ,
41
- shouldCreateSpanForRequest : _options . shouldCreateSpanForRequest ,
42
- } ;
43
- }
44
-
45
- /**
46
- * @inheritDoc
47
- */
48
- public setupOnce ( ) : void {
49
- const spans : Record < string , Span > = { } ;
50
-
51
- addFetchInstrumentationHandler ( handlerData => {
52
- if ( ! getClient ( ) ?. getIntegrationByName ?.( 'WinterCGFetch' ) ) {
53
- return ;
54
- }
55
-
56
- if ( isSentryRequestUrl ( handlerData . fetchData . url , getClient ( ) ) ) {
57
- return ;
58
- }
59
-
60
- instrumentFetchRequest (
61
- handlerData ,
62
- this . _shouldCreateSpan . bind ( this ) ,
63
- this . _shouldAttachTraceData . bind ( this ) ,
64
- spans ,
65
- 'auto.http.wintercg_fetch' ,
66
- ) ;
67
-
68
- if ( this . _options . breadcrumbs ) {
69
- createBreadcrumb ( handlerData ) ;
70
- }
71
- } ) ;
72
- }
46
+ const spans : Record < string , Span > = { } ;
73
47
74
48
/** Decides whether to attach trace data to the outgoing fetch request */
75
- private _shouldAttachTraceData ( url : string ) : boolean {
49
+ function _shouldAttachTraceData ( url : string ) : boolean {
76
50
const client = getClient ( ) ;
77
51
78
52
if ( ! client ) {
@@ -85,32 +59,86 @@ export class WinterCGFetch implements Integration {
85
59
return true ;
86
60
}
87
61
88
- const cachedDecision = this . _headersUrlMap . get ( url ) ;
62
+ const cachedDecision = _headersUrlMap . get ( url ) ;
89
63
if ( cachedDecision !== undefined ) {
90
64
return cachedDecision ;
91
65
}
92
66
93
67
const decision = stringMatchesSomePattern ( url , clientOptions . tracePropagationTargets ) ;
94
- this . _headersUrlMap . set ( url , decision ) ;
68
+ _headersUrlMap . set ( url , decision ) ;
95
69
return decision ;
96
70
}
97
71
98
72
/** Helper that wraps shouldCreateSpanForRequest option */
99
- private _shouldCreateSpan ( url : string ) : boolean {
100
- if ( this . _options . shouldCreateSpanForRequest === undefined ) {
73
+ function _shouldCreateSpan ( url : string ) : boolean {
74
+ if ( shouldCreateSpanForRequest === undefined ) {
101
75
return true ;
102
76
}
103
77
104
- const cachedDecision = this . _createSpanUrlMap . get ( url ) ;
78
+ const cachedDecision = _createSpanUrlMap . get ( url ) ;
105
79
if ( cachedDecision !== undefined ) {
106
80
return cachedDecision ;
107
81
}
108
82
109
- const decision = this . _options . shouldCreateSpanForRequest ( url ) ;
110
- this . _createSpanUrlMap . set ( url , decision ) ;
83
+ const decision = shouldCreateSpanForRequest ( url ) ;
84
+ _createSpanUrlMap . set ( url , decision ) ;
111
85
return decision ;
112
86
}
113
- }
87
+
88
+ return {
89
+ name : INTEGRATION_NAME ,
90
+ // TODO v8: Remove this again
91
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
92
+ setupOnce ( ) {
93
+ addFetchInstrumentationHandler ( handlerData => {
94
+ const client = getClient ( ) ;
95
+ if ( ! client || ! HAS_CLIENT_MAP . get ( client ) ) {
96
+ return ;
97
+ }
98
+
99
+ if ( isSentryRequestUrl ( handlerData . fetchData . url , client ) ) {
100
+ return ;
101
+ }
102
+
103
+ instrumentFetchRequest (
104
+ handlerData ,
105
+ _shouldCreateSpan ,
106
+ _shouldAttachTraceData ,
107
+ spans ,
108
+ 'auto.http.wintercg_fetch' ,
109
+ ) ;
110
+
111
+ if ( breadcrumbs ) {
112
+ createBreadcrumb ( handlerData ) ;
113
+ }
114
+ } ) ;
115
+ } ,
116
+ setup ( client ) {
117
+ HAS_CLIENT_MAP . set ( client , true ) ;
118
+ } ,
119
+ } ;
120
+ } ) satisfies IntegrationFn ;
121
+
122
+ export const winterCGFetchIntegration = defineIntegration ( _winterCGFetch ) ;
123
+
124
+ /**
125
+ * Creates spans and attaches tracing headers to fetch requests on WinterCG runtimes.
126
+ *
127
+ * @deprecated Use `winterCGFetchIntegration()` instead.
128
+ */
129
+ // eslint-disable-next-line deprecation/deprecation
130
+ export const WinterCGFetch = convertIntegrationFnToClass (
131
+ INTEGRATION_NAME ,
132
+ winterCGFetchIntegration ,
133
+ ) as IntegrationClass < Integration & { setupOnce : ( ) => void } > & {
134
+ new ( options ?: {
135
+ breadcrumbs : boolean ;
136
+ shouldCreateSpanForRequest ?: ( url : string ) => boolean ;
137
+ } ) : Integration ;
138
+ } ;
139
+
140
+ // eslint-disable-next-line deprecation/deprecation
141
+ export type WinterCGFetch = typeof WinterCGFetch ;
114
142
115
143
function createBreadcrumb ( handlerData : HandlerDataFetch ) : void {
116
144
const { startTimestamp, endTimestamp } = handlerData ;
0 commit comments