1
- import { getClient , getCurrentHub , getCurrentScope , hasTracingEnabled } from '@sentry/core' ;
1
+ import { getClient , getCurrentHub , getCurrentScope , hasTracingEnabled , runWithAsyncContext } from '@sentry/core' ;
2
2
import { flush } from '@sentry/node' ;
3
3
import type { Transaction } from '@sentry/types' ;
4
- import { extractRequestData , isString , logger } from '@sentry/utils' ;
4
+ import { extractRequestData , fill , isString , logger } from '@sentry/utils' ;
5
5
import { cwd } from 'process' ;
6
6
7
7
import { DEBUG_BUILD } from '../debug-build' ;
8
- import {
9
- createRoutes ,
10
- getTransactionName ,
11
- instrumentBuild ,
12
- isRequestHandlerWrapped ,
13
- startRequestHandlerTransaction ,
14
- } from '../instrumentServer' ;
8
+ import { createRoutes , getTransactionName , instrumentBuild , startRequestHandlerTransaction } from '../instrumentServer' ;
15
9
import type {
10
+ AppLoadContext ,
16
11
ExpressCreateRequestHandler ,
17
12
ExpressCreateRequestHandlerOptions ,
18
13
ExpressNextFunction ,
19
14
ExpressRequest ,
20
15
ExpressRequestHandler ,
21
16
ExpressResponse ,
17
+ GetLoadContextFunction ,
22
18
ReactRouterDomPkg ,
23
19
ServerBuild ,
24
20
} from '../vendor/types' ;
@@ -31,11 +27,6 @@ function wrapExpressRequestHandler(
31
27
) : ExpressRequestHandler {
32
28
const routes = createRoutes ( build . routes ) ;
33
29
34
- // If the core request handler is already wrapped, don't wrap Express handler which uses it.
35
- if ( isRequestHandlerWrapped ) {
36
- return origRequestHandler ;
37
- }
38
-
39
30
return async function (
40
31
this : unknown ,
41
32
req : ExpressRequest ,
@@ -54,33 +45,46 @@ function wrapExpressRequestHandler(
54
45
}
55
46
}
56
47
57
- // eslint-disable-next-line @typescript-eslint/unbound-method
58
- res . end = wrapEndMethod ( res . end ) ;
48
+ await runWithAsyncContext ( async ( ) => {
49
+ // eslint-disable-next-line @typescript-eslint/unbound-method
50
+ res . end = wrapEndMethod ( res . end ) ;
59
51
60
- const request = extractRequestData ( req ) ;
61
- const hub = getCurrentHub ( ) ;
62
- const options = getClient ( ) ?. getOptions ( ) ;
63
- const scope = getCurrentScope ( ) ;
52
+ const request = extractRequestData ( req ) ;
53
+ const hub = getCurrentHub ( ) ;
54
+ const options = getClient ( ) ?. getOptions ( ) ;
55
+ const scope = getCurrentScope ( ) ;
64
56
65
- scope . setSDKProcessingMetadata ( { request } ) ;
57
+ scope . setSDKProcessingMetadata ( { request } ) ;
66
58
67
- if ( ! options || ! hasTracingEnabled ( options ) || ! request . url || ! request . method ) {
68
- return origRequestHandler . call ( this , req , res , next ) ;
69
- }
59
+ if ( ! options || ! hasTracingEnabled ( options ) || ! request . url || ! request . method ) {
60
+ return origRequestHandler . call ( this , req , res , next ) ;
61
+ }
70
62
71
- const url = new URL ( request . url ) ;
72
- const [ name , source ] = getTransactionName ( routes , url , pkg ) ;
73
- const transaction = startRequestHandlerTransaction ( hub , name , source , {
74
- headers : {
75
- 'sentry-trace' : ( req . headers && isString ( req . headers [ 'sentry-trace' ] ) && req . headers [ 'sentry-trace' ] ) || '' ,
76
- baggage : ( req . headers && isString ( req . headers . baggage ) && req . headers . baggage ) || '' ,
77
- } ,
78
- method : request . method ,
63
+ const url = new URL ( request . url ) ;
64
+
65
+ const [ name , source ] = getTransactionName ( routes , url , pkg ) ;
66
+ const transaction = startRequestHandlerTransaction ( hub , name , source , {
67
+ headers : {
68
+ 'sentry-trace' : ( req . headers && isString ( req . headers [ 'sentry-trace' ] ) && req . headers [ 'sentry-trace' ] ) || '' ,
69
+ baggage : ( req . headers && isString ( req . headers . baggage ) && req . headers . baggage ) || '' ,
70
+ } ,
71
+ method : request . method ,
72
+ } ) ;
73
+ // save a link to the transaction on the response, so that even if there's an error (landing us outside of
74
+ // the domain), we can still finish it (albeit possibly missing some scope data)
75
+ ( res as AugmentedExpressResponse ) . __sentryTransaction = transaction ;
76
+ return origRequestHandler . call ( this , req , res , next ) ;
79
77
} ) ;
80
- // save a link to the transaction on the response, so that even if there's an error (landing us outside of
81
- // the domain), we can still finish it (albeit possibly missing some scope data)
82
- ( res as AugmentedExpressResponse ) . __sentryTransaction = transaction ;
83
- return origRequestHandler . call ( this , req , res , next ) ;
78
+ } ;
79
+ }
80
+
81
+ function wrapGetLoadContext ( origGetLoadContext : ( ) => AppLoadContext ) : GetLoadContextFunction {
82
+ return function ( this : unknown , req : ExpressRequest , res : ExpressResponse ) : AppLoadContext {
83
+ const loadContext = ( origGetLoadContext . call ( this , req , res ) || { } ) as AppLoadContext ;
84
+
85
+ loadContext [ '__sentry_express_wrapped__' ] = true ;
86
+
87
+ return loadContext ;
84
88
} ;
85
89
}
86
90
@@ -92,9 +96,18 @@ export function wrapExpressCreateRequestHandler(
92
96
// eslint-disable-next-line @typescript-eslint/no-explicit-any
93
97
) : ( options : any ) => ExpressRequestHandler {
94
98
// eslint-disable-next-line @typescript-eslint/no-explicit-any
95
- return function ( this : unknown , options : any ) : ExpressRequestHandler {
96
- const newBuild = instrumentBuild ( ( options as ExpressCreateRequestHandlerOptions ) . build ) ;
97
- const requestHandler = origCreateRequestHandler . call ( this , { ...options , build : newBuild } ) ;
99
+ return function ( this : unknown , options : ExpressCreateRequestHandlerOptions ) : ExpressRequestHandler {
100
+ if ( ! ( 'getLoadContext' in options ) ) {
101
+ options [ 'getLoadContext' ] = ( ) => ( { } ) ;
102
+ }
103
+
104
+ fill ( options , 'getLoadContext' , wrapGetLoadContext ) ;
105
+
106
+ const newBuild = instrumentBuild ( options . build , true ) ;
107
+ const requestHandler = origCreateRequestHandler . call ( this , {
108
+ ...options ,
109
+ build : newBuild ,
110
+ } ) ;
98
111
99
112
return wrapExpressRequestHandler ( requestHandler , newBuild ) ;
100
113
} ;
0 commit comments