1
1
import { Hub } from '@sentry/hub' ;
2
- import { EventProcessor , Integration , Severity , TransactionContext } from '@sentry/types' ;
3
- import { addInstrumentationHandler , getGlobalObject , logger , safeJoin } from '@sentry/utils' ;
2
+ import { EventProcessor , Integration , Transaction as TransactionType , TransactionContext } from '@sentry/types' ;
3
+ import { logger } from '@sentry/utils' ;
4
4
5
5
import { startIdleTransaction } from '../hubextensions' ;
6
- import { DEFAULT_IDLE_TIMEOUT , IdleTransaction } from '../idletransaction' ;
6
+ import { DEFAULT_IDLE_TIMEOUT } from '../idletransaction' ;
7
7
import { Span } from '../span' ;
8
- import { Location as LocationType } from '../types' ;
9
8
10
- const global = getGlobalObject < Window > ( ) ;
11
-
12
- type routingInstrumentationProcessor = ( context : TransactionContext ) => TransactionContext ;
13
-
14
- /**
15
- * Gets transaction context from a sentry-trace meta.
16
- */
17
- const setHeaderContext : routingInstrumentationProcessor = ctx => {
18
- const header = getMetaContent ( 'sentry-trace' ) ;
19
- if ( header ) {
20
- const span = Span . fromTraceparent ( header ) ;
21
- if ( span ) {
22
- return {
23
- ...ctx ,
24
- parentSpanId : span . parentSpanId ,
25
- sampled : span . sampled ,
26
- traceId : span . traceId ,
27
- } ;
28
- }
29
- }
30
-
31
- return ctx ;
32
- } ;
9
+ import { defaultRoutingInstrumentation , defaultBeforeNavigate } from './router' ;
33
10
34
11
/** Options for Browser Tracing integration */
35
12
export interface BrowserTracingOptions {
36
- /**
37
- * This is only if you want to debug in prod.
38
- * writeAsBreadcrumbs: Instead of having console.log statements we log messages to breadcrumbs
39
- * so you can investigate whats happening in production with your users to figure why things might not appear the
40
- * way you expect them to.
41
- *
42
- * Default: {
43
- * writeAsBreadcrumbs: false;
44
- * }
45
- */
46
- debug : {
47
- writeAsBreadcrumbs : boolean ;
48
- } ;
49
-
50
13
/**
51
14
* The time to wait in ms until the transaction will be finished. The transaction will use the end timestamp of
52
15
* the last finished span as the endtime for the transaction.
@@ -76,15 +39,17 @@ export interface BrowserTracingOptions {
76
39
*
77
40
* If undefined is returned, a pageload/navigation transaction will not be created.
78
41
*/
79
- beforeNavigate ( location : LocationType ) : string | undefined ;
42
+ beforeNavigate ( context : TransactionContext ) : TransactionContext | undefined ;
80
43
81
44
/**
82
- * Set to adjust transaction context before creation of transaction. Useful to set name/data/tags before
83
- * a transaction is sent. This option should be used by routing libraries to set context on transactions.
45
+ * Instrumentation that creates routing change transactions. By default creates
46
+ * pageload and navigation transactions.
84
47
*/
85
- // TODO: Should this be an option, or a static class variable and passed
86
- // in and we use something like `BrowserTracing.addRoutingProcessor()`
87
- routingInstrumentationProcessors : routingInstrumentationProcessor [ ] ;
48
+ routingInstrumentation < T extends TransactionType > (
49
+ startTransaction : ( context : TransactionContext ) => T | undefined ,
50
+ startTransactionOnPageLoad ?: boolean ,
51
+ startTransactionOnLocationChange ?: boolean ,
52
+ ) : void ;
88
53
}
89
54
90
55
/**
@@ -102,14 +67,9 @@ export class BrowserTracing implements Integration {
102
67
103
68
/** Browser Tracing integration options */
104
69
public options : BrowserTracingOptions = {
105
- beforeNavigate ( location : LocationType ) : string | undefined {
106
- return location . pathname ;
107
- } ,
108
- debug : {
109
- writeAsBreadcrumbs : false ,
110
- } ,
70
+ beforeNavigate : defaultBeforeNavigate ,
111
71
idleTimeout : DEFAULT_IDLE_TIMEOUT ,
112
- routingInstrumentationProcessors : [ ] ,
72
+ routingInstrumentation : defaultRoutingInstrumentation ,
113
73
startTransactionOnLocationChange : true ,
114
74
startTransactionOnPageLoad : true ,
115
75
} ;
@@ -119,8 +79,6 @@ export class BrowserTracing implements Integration {
119
79
*/
120
80
public name : string = BrowserTracing . id ;
121
81
122
- private _activeTransaction ?: IdleTransaction ;
123
-
124
82
private _getCurrentHub ?: ( ) => Hub ;
125
83
126
84
// navigationTransactionInvoker() -> Uses history API NavigationTransaction[]
@@ -138,116 +96,58 @@ export class BrowserTracing implements Integration {
138
96
public setupOnce ( _ : ( callback : EventProcessor ) => void , getCurrentHub : ( ) => Hub ) : void {
139
97
this . _getCurrentHub = getCurrentHub ;
140
98
141
- if ( ! global || ! global . location ) {
142
- return ;
143
- }
99
+ const { routingInstrumentation, startTransactionOnLocationChange, startTransactionOnPageLoad } = this . options ;
144
100
145
- this . _initRoutingInstrumentation ( ) ;
101
+ routingInstrumentation (
102
+ ( context : TransactionContext ) => this . _createRouteTransaction ( context ) ,
103
+ startTransactionOnPageLoad ,
104
+ startTransactionOnLocationChange ,
105
+ ) ;
146
106
}
147
107
148
- /** Start routing instrumentation */
149
- private _initRoutingInstrumentation ( ) : void {
150
- const { startTransactionOnPageLoad, startTransactionOnLocationChange } = this . options ;
151
-
152
- // TODO: is it fine that this is mutable operation? Could also do = [...routingInstr, setHeaderContext]?
153
- this . options . routingInstrumentationProcessors . push ( setHeaderContext ) ;
154
-
155
- if ( startTransactionOnPageLoad ) {
156
- this . _activeTransaction = this . _createRouteTransaction ( 'pageload' ) ;
157
- }
158
-
159
- let startingUrl : string | undefined = global . location . href ;
160
-
161
- // Could this be the one that changes?
162
- addInstrumentationHandler ( {
163
- callback : ( { to, from } : { to : string ; from ?: string } ) => {
164
- /**
165
- * This early return is there to account for some cases where navigation transaction
166
- * starts right after long running pageload. We make sure that if `from` is undefined
167
- * and that a valid `startingURL` exists, we don't uncessarily create a navigation transaction.
168
- *
169
- * This was hard to duplicate, but this behaviour stopped as soon as this fix
170
- * was applied. This issue might also only be caused in certain development environments
171
- * where the usage of a hot module reloader is causing errors.
172
- */
173
- if ( from === undefined && startingUrl && startingUrl . indexOf ( to ) !== - 1 ) {
174
- startingUrl = undefined ;
175
- return ;
176
- }
177
- if ( startTransactionOnLocationChange && from !== to ) {
178
- startingUrl = undefined ;
179
- if ( this . _activeTransaction ) {
180
- // We want to finish all current ongoing idle transactions as we
181
- // are navigating to a new page.
182
- this . _activeTransaction . finishIdleTransaction ( ) ;
183
- }
184
- this . _activeTransaction = this . _createRouteTransaction ( 'navigation' ) ;
185
- }
186
- } ,
187
- type : 'history' ,
188
- } ) ;
189
- }
190
-
191
- /** Create pageload/navigation idle transaction. */
192
- private _createRouteTransaction (
193
- op : 'pageload' | 'navigation' ,
194
- context ?: TransactionContext ,
195
- ) : IdleTransaction | undefined {
108
+ /** Create routing idle transaction. */
109
+ private _createRouteTransaction ( context : TransactionContext ) : TransactionType | undefined {
196
110
if ( ! this . _getCurrentHub ) {
111
+ logger . warn ( `[Tracing] Did not creeate ${ context . op } idleTransaction due to invalid _getCurrentHub` ) ;
197
112
return undefined ;
198
113
}
199
114
200
- const { beforeNavigate, idleTimeout, routingInstrumentationProcessors } = this . options ;
115
+ const { beforeNavigate, idleTimeout } = this . options ;
201
116
202
117
// if beforeNavigate returns undefined, we should not start a transaction.
203
- const name = beforeNavigate ( global . location ) ;
204
- if ( name === undefined ) {
205
- this . _log ( `[Tracing] Cancelling ${ op } idleTransaction due to beforeNavigate:` ) ;
118
+ const ctx = beforeNavigate ( {
119
+ ...context ,
120
+ ...getHeaderContext ( ) ,
121
+ } ) ;
122
+
123
+ if ( ctx === undefined ) {
124
+ logger . log ( `[Tracing] Did not create ${ context . op } idleTransaction due to beforeNavigate` ) ;
206
125
return undefined ;
207
126
}
208
127
209
- const ctx = createContextFromProcessors ( { name, op, ...context } , routingInstrumentationProcessors ) ;
210
-
211
128
const hub = this . _getCurrentHub ( ) ;
212
- this . _log ( `[Tracing] starting ${ op } idleTransaction on scope with context:` , ctx ) ;
213
- const activeTransaction = startIdleTransaction ( hub , ctx , idleTimeout , true ) ;
214
-
215
- return activeTransaction ;
216
- }
217
-
218
- /**
219
- * Uses logger.log to log things in the SDK or as breadcrumbs if defined in options
220
- */
221
- private _log ( ...args : any [ ] ) : void {
222
- if ( this . options && this . options . debug && this . options . debug . writeAsBreadcrumbs ) {
223
- const _getCurrentHub = this . _getCurrentHub ;
224
- if ( _getCurrentHub ) {
225
- _getCurrentHub ( ) . addBreadcrumb ( {
226
- category : 'tracing' ,
227
- level : Severity . Debug ,
228
- message : safeJoin ( args , ' ' ) ,
229
- type : 'debug' ,
230
- } ) ;
231
- }
232
- }
233
- logger . log ( ...args ) ;
129
+ logger . log ( `[Tracing] starting ${ ctx . op } idleTransaction on scope with context:` , ctx ) ;
130
+ return startIdleTransaction ( hub , ctx , idleTimeout , true ) as TransactionType ;
234
131
}
235
132
}
236
133
237
- /** Creates transaction context from a set of processors */
238
- export function createContextFromProcessors (
239
- context : TransactionContext ,
240
- processors : routingInstrumentationProcessor [ ] ,
241
- ) : TransactionContext {
242
- let ctx = context ;
243
- for ( const processor of processors ) {
244
- const newContext = processor ( context ) ;
245
- if ( newContext && newContext . name && newContext . op ) {
246
- ctx = newContext ;
134
+ /**
135
+ * Gets transaction context from a sentry-trace meta.
136
+ */
137
+ function getHeaderContext ( ) : Partial < TransactionContext > {
138
+ const header = getMetaContent ( 'sentry-trace' ) ;
139
+ if ( header ) {
140
+ const span = Span . fromTraceparent ( header ) ;
141
+ if ( span ) {
142
+ return {
143
+ parentSpanId : span . parentSpanId ,
144
+ sampled : span . sampled ,
145
+ traceId : span . traceId ,
146
+ } ;
247
147
}
248
148
}
249
149
250
- return ctx ;
150
+ return { } ;
251
151
}
252
152
253
153
/** Returns the value of a meta tag */
0 commit comments