1
- import { EventProcessor , Hub , Integration } from '@sentry/types' ;
1
+ import { Integration , Transaction } from '@sentry/types' ;
2
2
import { logger } from '@sentry/utils' ;
3
3
// tslint:disable-next-line:no-implicit-dependencies
4
4
import { Application , ErrorRequestHandler , NextFunction , Request , RequestHandler , Response } from 'express' ;
5
5
6
+ /**
7
+ * Internal helper for `__sentry_transaction`
8
+ * @hidden
9
+ */
10
+ interface SentryTracingResponse {
11
+ __sentry_transaction ?: Transaction ;
12
+ }
13
+
6
14
/**
7
15
* Express integration
8
16
*
@@ -35,12 +43,12 @@ export class Express implements Integration {
35
43
/**
36
44
* @inheritDoc
37
45
*/
38
- public setupOnce ( _addGlobalEventProcessor : ( callback : EventProcessor ) => void , getCurrentHub : ( ) => Hub ) : void {
46
+ public setupOnce ( ) : void {
39
47
if ( ! this . _app ) {
40
48
logger . error ( 'ExpressIntegration is missing an Express instance' ) ;
41
49
return ;
42
50
}
43
- instrumentMiddlewares ( this . _app , getCurrentHub ) ;
51
+ instrumentMiddlewares ( this . _app ) ;
44
52
}
45
53
}
46
54
@@ -56,40 +64,66 @@ export class Express implements Integration {
56
64
* // error handler
57
65
* app.use(function (err, req, res, next) { ... })
58
66
*/
59
- function wrap ( fn : Function , getCurrentHub : ( ) => Hub ) : RequestHandler | ErrorRequestHandler {
67
+ function wrap ( fn : Function ) : RequestHandler | ErrorRequestHandler {
60
68
const arrity = fn . length ;
61
69
62
70
switch ( arrity ) {
63
71
case 2 : {
64
- return function ( this : NodeJS . Global , _req : Request , res : Response ) : any {
65
- const span = getCurrentHub ( ) . startSpan ( {
66
- description : fn . name ,
67
- op : 'middleware' ,
68
- } ) ;
69
- res . once ( 'finish' , ( ) => span . finish ( ) ) ;
72
+ return function ( this : NodeJS . Global , _req : Request , res : Response & SentryTracingResponse ) : any {
73
+ const transaction = res . __sentry_transaction ;
74
+ if ( transaction ) {
75
+ const span = transaction . startChild ( {
76
+ description : fn . name ,
77
+ op : 'middleware' ,
78
+ } ) ;
79
+ res . once ( 'finish' , ( ) => {
80
+ span . finish ( ) ;
81
+ } ) ;
82
+ }
70
83
return fn . apply ( this , arguments ) ;
71
84
} ;
72
85
}
73
86
case 3 : {
74
- return function ( this : NodeJS . Global , req : Request , res : Response , next : NextFunction ) : any {
75
- const span = getCurrentHub ( ) . startSpan ( {
76
- description : fn . name ,
77
- op : 'middleware' ,
78
- } ) ;
87
+ return function (
88
+ this : NodeJS . Global ,
89
+ req : Request ,
90
+ res : Response & SentryTracingResponse ,
91
+ next : NextFunction ,
92
+ ) : any {
93
+ const transaction = res . __sentry_transaction ;
94
+ const span =
95
+ transaction &&
96
+ transaction . startChild ( {
97
+ description : fn . name ,
98
+ op : 'middleware' ,
99
+ } ) ;
79
100
fn . call ( this , req , res , function ( this : NodeJS . Global ) : any {
80
- span . finish ( ) ;
101
+ if ( span ) {
102
+ span . finish ( ) ;
103
+ }
81
104
return next . apply ( this , arguments ) ;
82
105
} ) ;
83
106
} ;
84
107
}
85
108
case 4 : {
86
- return function ( this : NodeJS . Global , err : any , req : Request , res : Response , next : NextFunction ) : any {
87
- const span = getCurrentHub ( ) . startSpan ( {
88
- description : fn . name ,
89
- op : 'middleware' ,
90
- } ) ;
109
+ return function (
110
+ this : NodeJS . Global ,
111
+ err : any ,
112
+ req : Request ,
113
+ res : Response & SentryTracingResponse ,
114
+ next : NextFunction ,
115
+ ) : any {
116
+ const transaction = res . __sentry_transaction ;
117
+ const span =
118
+ transaction &&
119
+ transaction . startChild ( {
120
+ description : fn . name ,
121
+ op : 'middleware' ,
122
+ } ) ;
91
123
fn . call ( this , err , req , res , function ( this : NodeJS . Global ) : any {
92
- span . finish ( ) ;
124
+ if ( span ) {
125
+ span . finish ( ) ;
126
+ }
93
127
return next . apply ( this , arguments ) ;
94
128
} ) ;
95
129
} ;
@@ -110,16 +144,16 @@ function wrap(fn: Function, getCurrentHub: () => Hub): RequestHandler | ErrorReq
110
144
* app.use([<path>], <fn>, ...<fn>)
111
145
* app.use([<path>], ...<fn>[])
112
146
*/
113
- function wrapUseArgs ( args : IArguments , getCurrentHub : ( ) => Hub ) : unknown [ ] {
147
+ function wrapUseArgs ( args : IArguments ) : unknown [ ] {
114
148
return Array . from ( args ) . map ( ( arg : unknown ) => {
115
149
if ( typeof arg === 'function' ) {
116
- return wrap ( arg , getCurrentHub ) ;
150
+ return wrap ( arg ) ;
117
151
}
118
152
119
153
if ( Array . isArray ( arg ) ) {
120
154
return arg . map ( ( a : unknown ) => {
121
155
if ( typeof a === 'function' ) {
122
- return wrap ( a , getCurrentHub ) ;
156
+ return wrap ( a ) ;
123
157
}
124
158
return a ;
125
159
} ) ;
@@ -132,10 +166,10 @@ function wrapUseArgs(args: IArguments, getCurrentHub: () => Hub): unknown[] {
132
166
/**
133
167
* Patches original app.use to utilize our tracing functionality
134
168
*/
135
- function instrumentMiddlewares ( app : Application , getCurrentHub : ( ) => Hub ) : Application {
169
+ function instrumentMiddlewares ( app : Application ) : Application {
136
170
const originalAppUse = app . use ;
137
171
app . use = function ( ) : any {
138
- return originalAppUse . apply ( this , wrapUseArgs ( arguments , getCurrentHub ) ) ;
172
+ return originalAppUse . apply ( this , wrapUseArgs ( arguments ) ) ;
139
173
} ;
140
174
return app ;
141
175
}
0 commit comments