1
- /* eslint-disable max-lines */
2
- import type { RequestEventData , Span , TransactionSource , WrappedFunction } from '@sentry/core' ;
1
+ import type { RequestEventData } from '@sentry/core' ;
3
2
import {
4
- SEMANTIC_ATTRIBUTE_SENTRY_OP ,
5
- SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ,
6
- SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ,
7
3
continueTrace ,
8
4
fill ,
9
- getActiveSpan ,
10
5
getClient ,
11
- getRootSpan ,
12
6
getTraceData ,
13
7
hasTracingEnabled ,
14
8
isNodeEnv ,
15
9
loadModule ,
16
10
logger ,
17
- setHttpStatus ,
18
- spanToJSON ,
19
- startSpan ,
20
11
winterCGRequestToRequestData ,
21
12
withIsolationScope ,
22
13
} from '@sentry/core' ;
23
14
import { DEBUG_BUILD } from './debug-build' ;
24
- import { captureRemixServerException , errorHandleDataFunction , errorHandleDocumentRequestFunction } from './errors' ;
25
- import type { RemixOptions } from './remixOptions' ;
26
- import { createRoutes , getTransactionName } from './utils' ;
15
+ import { captureRemixServerException } from './errors' ;
27
16
import { extractData , isDeferredData , isResponse , isRouteErrorResponse , json } from './vendor/response' ;
28
17
import type {
29
18
AppData ,
30
19
AppLoadContext ,
31
20
CreateRequestHandlerFunction ,
32
21
DataFunction ,
33
22
DataFunctionArgs ,
34
- EntryContext ,
35
- HandleDocumentRequestFunction ,
36
23
RemixRequest ,
37
24
RequestHandler ,
38
25
ServerBuild ,
39
- ServerRoute ,
40
26
ServerRouteManifest ,
41
27
} from './vendor/types' ;
42
28
@@ -94,93 +80,6 @@ export function wrapHandleErrorWithSentry(
94
80
} ;
95
81
}
96
82
97
- function makeWrappedDocumentRequestFunction ( autoInstrumentRemix ?: boolean ) {
98
- return function ( origDocumentRequestFunction : HandleDocumentRequestFunction ) : HandleDocumentRequestFunction {
99
- return async function (
100
- this : unknown ,
101
- request : Request ,
102
- responseStatusCode : number ,
103
- responseHeaders : Headers ,
104
- context : EntryContext ,
105
- loadContext ?: Record < string , unknown > ,
106
- ) : Promise < Response > {
107
- const documentRequestContext = {
108
- request,
109
- responseStatusCode,
110
- responseHeaders,
111
- context,
112
- loadContext,
113
- } ;
114
-
115
- if ( ! autoInstrumentRemix ) {
116
- const activeSpan = getActiveSpan ( ) ;
117
- const rootSpan = activeSpan && getRootSpan ( activeSpan ) ;
118
-
119
- const name = rootSpan ? spanToJSON ( rootSpan ) . description : undefined ;
120
-
121
- return startSpan (
122
- {
123
- // If we don't have a root span, `onlyIfParent` will lead to the span not being created anyhow
124
- // So we don't need to care too much about the fallback name, it's just for typing purposes....
125
- name : name || '<unknown>' ,
126
- onlyIfParent : true ,
127
- attributes : {
128
- method : request . method ,
129
- url : request . url ,
130
- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.function.remix' ,
131
- [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'function.remix.document_request' ,
132
- } ,
133
- } ,
134
- ( ) => {
135
- return errorHandleDocumentRequestFunction . call ( this , origDocumentRequestFunction , documentRequestContext ) ;
136
- } ,
137
- ) ;
138
- } else {
139
- return errorHandleDocumentRequestFunction . call ( this , origDocumentRequestFunction , documentRequestContext ) ;
140
- }
141
- } ;
142
- } ;
143
- }
144
-
145
- function makeWrappedDataFunction (
146
- origFn : DataFunction ,
147
- id : string ,
148
- name : 'action' | 'loader' ,
149
- autoInstrumentRemix ?: boolean ,
150
- ) : DataFunction {
151
- return async function ( this : unknown , args : DataFunctionArgs ) : Promise < Response | AppData > {
152
- if ( ! autoInstrumentRemix ) {
153
- return startSpan (
154
- {
155
- op : `function.remix.${ name } ` ,
156
- name : id ,
157
- attributes : {
158
- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.ui.remix' ,
159
- name,
160
- } ,
161
- } ,
162
- ( span : Span ) => {
163
- return errorHandleDataFunction . call ( this , origFn , name , args , span ) ;
164
- } ,
165
- ) ;
166
- } else {
167
- return errorHandleDataFunction . call ( this , origFn , name , args ) ;
168
- }
169
- } ;
170
- }
171
-
172
- const makeWrappedAction =
173
- ( id : string , autoInstrumentRemix ?: boolean ) =>
174
- ( origAction : DataFunction ) : DataFunction => {
175
- return makeWrappedDataFunction ( origAction , id , 'action' , autoInstrumentRemix ) ;
176
- } ;
177
-
178
- const makeWrappedLoader =
179
- ( id : string , autoInstrumentRemix ?: boolean ) =>
180
- ( origLoader : DataFunction ) : DataFunction => {
181
- return makeWrappedDataFunction ( origLoader , id , 'loader' , autoInstrumentRemix ) ;
182
- } ;
183
-
184
83
function getTraceAndBaggage ( ) : {
185
84
sentryTrace ?: string ;
186
85
sentryBaggage ?: string ;
@@ -241,33 +140,14 @@ function makeWrappedRootLoader() {
241
140
} ;
242
141
}
243
142
244
- function wrapRequestHandler (
245
- origRequestHandler : RequestHandler ,
246
- build : ServerBuild | ( ( ) => ServerBuild | Promise < ServerBuild > ) ,
247
- autoInstrumentRemix : boolean ,
248
- ) : RequestHandler {
249
- let resolvedBuild : ServerBuild ;
250
- let routes : ServerRoute [ ] ;
251
- let name : string ;
252
- let source : TransactionSource ;
253
-
143
+ function wrapRequestHandler ( origRequestHandler : RequestHandler ) : RequestHandler {
254
144
return async function ( this : unknown , request : RemixRequest , loadContext ?: AppLoadContext ) : Promise < Response > {
255
145
const upperCaseMethod = request . method . toUpperCase ( ) ;
256
146
// We don't want to wrap OPTIONS and HEAD requests
257
147
if ( upperCaseMethod === 'OPTIONS' || upperCaseMethod === 'HEAD' ) {
258
148
return origRequestHandler . call ( this , request , loadContext ) ;
259
149
}
260
150
261
- if ( ! autoInstrumentRemix ) {
262
- if ( typeof build === 'function' ) {
263
- resolvedBuild = await build ( ) ;
264
- } else {
265
- resolvedBuild = build ;
266
- }
267
-
268
- routes = createRoutes ( resolvedBuild . routes ) ;
269
- }
270
-
271
151
return withIsolationScope ( async isolationScope => {
272
152
const options = getClient ( ) ?. getOptions ( ) ;
273
153
@@ -279,13 +159,6 @@ function wrapRequestHandler(
279
159
DEBUG_BUILD && logger . warn ( 'Failed to normalize Remix request' ) ;
280
160
}
281
161
282
- if ( ! autoInstrumentRemix ) {
283
- const url = new URL ( request . url ) ;
284
- [ name , source ] = getTransactionName ( routes , url ) ;
285
-
286
- isolationScope . setTransactionName ( name ) ;
287
- }
288
-
289
162
isolationScope . setSDKProcessingMetadata ( { normalizedRequest } ) ;
290
163
291
164
if ( ! options || ! hasTracingEnabled ( options ) ) {
@@ -298,62 +171,20 @@ function wrapRequestHandler(
298
171
baggage : request . headers . get ( 'baggage' ) || '' ,
299
172
} ,
300
173
async ( ) => {
301
- if ( ! autoInstrumentRemix ) {
302
- return startSpan (
303
- {
304
- name,
305
- attributes : {
306
- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.http.remix' ,
307
- [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : source ,
308
- [ SEMANTIC_ATTRIBUTE_SENTRY_OP ] : 'http.server' ,
309
- method : request . method ,
310
- } ,
311
- } ,
312
- async span => {
313
- const res = ( await origRequestHandler . call ( this , request , loadContext ) ) as Response ;
314
-
315
- if ( isResponse ( res ) ) {
316
- setHttpStatus ( span , res . status ) ;
317
- }
318
-
319
- return res ;
320
- } ,
321
- ) ;
322
- }
323
-
324
174
return ( await origRequestHandler . call ( this , request , loadContext ) ) as Response ;
325
175
} ,
326
176
) ;
327
177
} ) ;
328
178
} ;
329
179
}
330
180
331
- function instrumentBuildCallback ( build : ServerBuild , autoInstrumentRemix : boolean ) : ServerBuild {
181
+ function instrumentBuildCallback ( build : ServerBuild ) : ServerBuild {
332
182
const routes : ServerRouteManifest = { } ;
333
183
const wrappedEntry = { ...build . entry , module : { ...build . entry . module } } ;
334
184
335
- // Not keeping boolean flags like it's done for `requestHandler` functions,
336
- // Because the build can change between build and runtime.
337
- // So if there is a new `loader` or`action` or `documentRequest` after build.
338
- // We should be able to wrap them, as they may not be wrapped before.
339
- const defaultExport = wrappedEntry . module . default as undefined | WrappedFunction ;
340
- if ( defaultExport && ! defaultExport . __sentry_original__ ) {
341
- fill ( wrappedEntry . module , 'default' , makeWrappedDocumentRequestFunction ( autoInstrumentRemix ) ) ;
342
- }
343
-
344
185
for ( const [ id , route ] of Object . entries ( build . routes ) ) {
345
186
const wrappedRoute = { ...route , module : { ...route . module } } ;
346
187
347
- const routeAction = wrappedRoute . module . action as undefined | WrappedFunction ;
348
- if ( routeAction && ! routeAction . __sentry_original__ ) {
349
- fill ( wrappedRoute . module , 'action' , makeWrappedAction ( id , autoInstrumentRemix ) ) ;
350
- }
351
-
352
- const routeLoader = wrappedRoute . module . loader as undefined | WrappedFunction ;
353
- if ( routeLoader && ! routeLoader . __sentry_original__ ) {
354
- fill ( wrappedRoute . module , 'loader' , makeWrappedLoader ( id , autoInstrumentRemix ) ) ;
355
- }
356
-
357
188
// Entry module should have a loader function to provide `sentry-trace` and `baggage`
358
189
// They will be available for the root `meta` function as `data.sentryTrace` and `data.sentryBaggage`
359
190
if ( ! wrappedRoute . parentId ) {
@@ -376,48 +207,43 @@ function instrumentBuildCallback(build: ServerBuild, autoInstrumentRemix: boolea
376
207
*/
377
208
export function instrumentBuild (
378
209
build : ServerBuild | ( ( ) => ServerBuild | Promise < ServerBuild > ) ,
379
- options : RemixOptions ,
380
210
) : ServerBuild | ( ( ) => ServerBuild | Promise < ServerBuild > ) {
381
- // eslint-disable-next-line deprecation/deprecation
382
- const autoInstrumentRemix = options ?. autoInstrumentRemix || false ;
383
-
384
211
if ( typeof build === 'function' ) {
385
212
return function ( ) {
386
213
const resolvedBuild = build ( ) ;
387
214
388
215
if ( resolvedBuild instanceof Promise ) {
389
216
return resolvedBuild . then ( build => {
390
- return instrumentBuildCallback ( build , autoInstrumentRemix ) ;
217
+ return instrumentBuildCallback ( build ) ;
391
218
} ) ;
392
219
} else {
393
- return instrumentBuildCallback ( resolvedBuild , autoInstrumentRemix ) ;
220
+ return instrumentBuildCallback ( resolvedBuild ) ;
394
221
}
395
222
} ;
396
223
} else {
397
- return instrumentBuildCallback ( build , autoInstrumentRemix ) ;
224
+ return instrumentBuildCallback ( build ) ;
398
225
}
399
226
}
400
227
401
- const makeWrappedCreateRequestHandler = ( options : RemixOptions ) =>
228
+ const makeWrappedCreateRequestHandler = ( ) =>
402
229
function ( origCreateRequestHandler : CreateRequestHandlerFunction ) : CreateRequestHandlerFunction {
403
230
return function (
404
231
this : unknown ,
405
232
build : ServerBuild | ( ( ) => Promise < ServerBuild > ) ,
406
233
...args : unknown [ ]
407
234
) : RequestHandler {
408
- const newBuild = instrumentBuild ( build , options ) ;
235
+ const newBuild = instrumentBuild ( build ) ;
409
236
const requestHandler = origCreateRequestHandler . call ( this , newBuild , ...args ) ;
410
237
411
- // eslint-disable-next-line deprecation/deprecation
412
- return wrapRequestHandler ( requestHandler , newBuild , options . autoInstrumentRemix || false ) ;
238
+ return wrapRequestHandler ( requestHandler ) ;
413
239
} ;
414
240
} ;
415
241
416
242
/**
417
243
* Monkey-patch Remix's `createRequestHandler` from `@remix-run/server-runtime`
418
244
* which Remix Adapters (https://remix.run/docs/en/v1/api/remix) use underneath.
419
245
*/
420
- export function instrumentServer ( options : RemixOptions ) : void {
246
+ export function instrumentServer ( ) : void {
421
247
const pkg = loadModule < {
422
248
createRequestHandler : CreateRequestHandlerFunction ;
423
249
} > ( '@remix-run/server-runtime' ) ;
@@ -428,5 +254,5 @@ export function instrumentServer(options: RemixOptions): void {
428
254
return ;
429
255
}
430
256
431
- fill ( pkg , 'createRequestHandler' , makeWrappedCreateRequestHandler ( options ) ) ;
257
+ fill ( pkg , 'createRequestHandler' , makeWrappedCreateRequestHandler ( ) ) ;
432
258
}
0 commit comments