@@ -65,20 +65,21 @@ export class HttpPlugin extends classes.BasePlugin {
6565
6666 this . logger . debug ( 'applying pacth to %s@%s' , this . moduleName , this . version ) ;
6767
68- shimmer . wrap ( moduleExports , 'request' , this . patchOutgoingRequest ( ) ) ;
68+ shimmer . wrap (
69+ moduleExports , 'request' , this . getPatchOutgoingRequestFunction ( ) ) ;
6970
7071 // In Node 8, http.get calls a private request method, therefore we patch it
7172 // here too.
7273 if ( semver . satisfies ( version , '>=8.0.0' ) ) {
73- shimmer . wrap ( moduleExports , 'get' , this . patchOutgoingRequest ( ) ) ;
74+ shimmer . wrap (
75+ moduleExports , 'get' , this . getPatchOutgoingRequestFunction ( ) ) ;
7476 }
7577
7678 if ( moduleExports && moduleExports . Server &&
7779 moduleExports . Server . prototype ) {
7880 shimmer . wrap (
79- moduleExports && moduleExports . Server &&
80- moduleExports . Server . prototype ,
81- 'emit' as never , this . patchIncomingRequest ( ) ) ;
81+ moduleExports . Server . prototype , 'emit' ,
82+ this . getPatchIncomingRequestFunction ( ) ) ;
8283 } else {
8384 this . logger . error (
8485 'Could not apply patch to %s.emit. Interface is not as expected.' ,
@@ -97,95 +98,96 @@ export class HttpPlugin extends classes.BasePlugin {
9798 }
9899 if ( this . moduleExports && this . moduleExports . Server &&
99100 this . moduleExports . Server . prototype ) {
100- shimmer . unwrap (
101- this . moduleExports && this . moduleExports . Server &&
102- this . moduleExports . Server . prototype ,
103- 'emit' ) ;
101+ shimmer . unwrap ( this . moduleExports . Server . prototype , 'emit' ) ;
104102 }
105103 }
106104
107105
108106 /**
109107 * Creates spans for incoming requests, restoring spans' context if applied.
110108 */
111- protected patchIncomingRequest ( ) {
112- return ( original : RequestFunction ) => {
109+ protected getPatchIncomingRequestFunction ( ) {
110+ return ( original : ( event : string ) => boolean ) => {
113111 const plugin = this ;
114- return function incomingRequest (
115- event : string , request : httpModule . IncomingMessage ,
116- response : httpModule . ServerResponse ) :
117- httpModule . ClientRequest {
118- // Only traces request events
119- if ( event !== 'request' ) {
120- return original . apply ( this , arguments ) ;
121- }
122-
123- plugin . logger . debug ( '%s plugin incomingRequest' , plugin . moduleName ) ;
124- const propagation = plugin . tracer . propagation ;
125- const headers = request . headers ;
126- const getter : types . HeaderGetter = {
127- getHeader ( name : string ) {
128- return headers [ name ] ;
129- }
130- } ;
131-
132- const traceOptions = {
133- name : url . parse ( request . url ) . pathname ,
134- type : 'SERVER' ,
135- spanContext : propagation ? propagation . extract ( getter ) : null
136- } ;
137-
138- return plugin . tracer . startRootSpan ( traceOptions , rootSpan => {
139- if ( ! rootSpan ) return original . apply ( this , arguments ) ;
140-
141- plugin . tracer . wrapEmitter ( request ) ;
142- plugin . tracer . wrapEmitter ( response ) ;
143-
144- // Wraps end (inspired by:
145- // https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/blob/master/src/plugins/ plugin-connect.ts#L75)
146- const originalEnd = response . end ;
147-
148- response . end = function ( this : httpModule . ServerResponse ) {
149- response . end = originalEnd ;
150- const returned = response . end . apply ( this , arguments ) ;
151-
152- const requestUrl = url . parse ( request . url ) ;
153- const host = headers . host || 'localhost' ;
154- const userAgent =
155- ( headers [ 'user-agent' ] || headers [ 'User-Agent' ] ) as string ;
156-
157- rootSpan . addAttribute (
158- HttpPlugin . ATTRIBUTE_HTTP_HOST ,
159- host . replace (
160- / ^ ( . * ) ( \: [ 0 - 9 ] { 1 , 5 } ) / ,
161- '$1' ,
162- ) ) ;
163- rootSpan . addAttribute (
164- HttpPlugin . ATTRIBUTE_HTTP_METHOD , request . method ) ;
165- rootSpan . addAttribute (
166- HttpPlugin . ATTRIBUTE_HTTP_PATH , requestUrl . pathname ) ;
167- rootSpan . addAttribute (
168- HttpPlugin . ATTRIBUTE_HTTP_ROUTE , requestUrl . path ) ;
169- rootSpan . addAttribute (
170- HttpPlugin . ATTRIBUTE_HTTP_USER_AGENT , userAgent ) ;
171-
172- rootSpan . addAttribute (
173- HttpPlugin . ATTRIBUTE_HTTP_STATUS_CODE ,
174- response . statusCode . toString ( ) ) ;
175-
176- rootSpan . status = plugin . traceStatus ( response . statusCode ) ;
177-
178- // Message Event ID is not defined
179- rootSpan . addMessageEvent (
180- 'MessageEventTypeRecv' , uuid . v4 ( ) . split ( '-' ) . join ( '' ) ) ;
181-
182- rootSpan . end ( ) ;
183- return returned ;
184- } ;
185-
186- return original . apply ( this , arguments ) ;
187- } ) ;
112+ // This function's signature is that of an event listener, which can have
113+ // any number of variable-type arguments.
114+ // tslint:disable-next-line:no-any
115+ return function incomingRequest ( event : string , ... args : any [ ] ) : boolean {
116+ // Only traces request events
117+ if ( event !== 'request' ) {
118+ return original . apply ( this , arguments ) ;
119+ }
120+
121+ const request : httpModule . IncomingMessage = args [ 0 ] ;
122+ const response : httpModule . ServerResponse = args [ 1 ] ;
123+
124+ plugin . logger . debug ( '%s plugin incomingRequest' , plugin . moduleName ) ;
125+ const propagation = plugin . tracer . propagation ;
126+ const headers = request . headers ;
127+ const getter : types . HeaderGetter = {
128+ getHeader ( name : string ) {
129+ return headers [ name ] ;
130+ }
131+ } ;
132+
133+ const traceOptions = {
134+ name : url . parse ( request . url ) . pathname ,
135+ type : 'SERVER' ,
136+ spanContext : propagation ? propagation . extract ( getter ) : null
137+ } ;
138+
139+ return plugin . tracer . startRootSpan ( traceOptions , rootSpan => {
140+ if ( ! rootSpan ) return original . apply ( this , arguments ) ;
141+
142+ plugin . tracer . wrapEmitter ( request ) ;
143+ plugin . tracer . wrapEmitter ( response ) ;
144+
145+ // Wraps end (inspired by:
146+ // https://github.com/GoogleCloudPlatform/cloud-trace-nodejs/blob/master/src/plugins/plugin-connect.ts#L75)
147+ const originalEnd = response . end ;
148+
149+ response . end = function ( this : httpModule . ServerResponse ) {
150+ response . end = originalEnd ;
151+ const returned = response . end . apply ( this , arguments ) ;
152+
153+ const requestUrl = url . parse ( request . url ) ;
154+ const host = headers . host || 'localhost' ;
155+ const userAgent =
156+ ( headers [ 'user-agent' ] || headers [ 'User-Agent' ] ) as string ;
157+
158+ rootSpan . addAttribute (
159+ HttpPlugin . ATTRIBUTE_HTTP_HOST ,
160+ host . replace (
161+ / ^ ( . * ) ( \: [ 0 - 9 ] { 1 , 5 } ) / ,
162+ '$1' ,
163+ ) ) ;
164+ rootSpan . addAttribute (
165+ HttpPlugin . ATTRIBUTE_HTTP_METHOD , request . method ) ;
166+ rootSpan . addAttribute (
167+ HttpPlugin . ATTRIBUTE_HTTP_PATH , requestUrl . pathname ) ;
168+ rootSpan . addAttribute (
169+ HttpPlugin . ATTRIBUTE_HTTP_ROUTE , requestUrl . path ) ;
170+ rootSpan . addAttribute (
171+ HttpPlugin . ATTRIBUTE_HTTP_USER_AGENT , userAgent ) ;
172+
173+ rootSpan . addAttribute (
174+ HttpPlugin . ATTRIBUTE_HTTP_STATUS_CODE ,
175+ response . statusCode . toString ( ) ) ;
176+
177+ rootSpan . status =
178+ HttpPlugin . convertTraceStatus ( response . statusCode ) ;
179+
180+ // Message Event ID is not defined
181+ rootSpan . addMessageEvent (
182+ 'MessageEventTypeRecv' , uuid . v4 ( ) . split ( '-' ) . join ( '' ) ) ;
183+
184+ rootSpan . end ( ) ;
185+ return returned ;
188186 } ;
187+
188+ return original . apply ( this , arguments ) ;
189+ } ) ;
190+ } ;
189191 } ;
190192 }
191193
@@ -194,7 +196,7 @@ export class HttpPlugin extends classes.BasePlugin {
194196 * Creates spans for outgoing requests, sending spans' context for distributed
195197 * tracing.
196198 */
197- protected patchOutgoingRequest ( ) {
199+ protected getPatchOutgoingRequestFunction ( ) {
198200 return ( original : types . Func < httpModule . ClientRequest > ) :
199201 types . Func < httpModule . ClientRequest > => {
200202 const plugin = this ;
@@ -237,12 +239,14 @@ export class HttpPlugin extends classes.BasePlugin {
237239 if ( ! plugin . tracer . currentRootSpan ) {
238240 plugin . logger . debug ( 'outgoingRequest starting a root span' ) ;
239241 return plugin . tracer . startRootSpan (
240- traceOptions , plugin . makeRequestTrace ( request , options , plugin ) ) ;
242+ traceOptions ,
243+ plugin . getMakeRequestTraceFunction ( request , options , plugin ) ) ;
241244 } else {
242245 plugin . logger . debug ( 'outgoingRequest starting a child span' ) ;
243246 const span = plugin . tracer . startChildSpan (
244247 traceOptions . name , traceOptions . type ) ;
245- return ( plugin . makeRequestTrace ( request , options , plugin ) ) ( span ) ;
248+ return ( plugin . getMakeRequestTraceFunction ( request , options , plugin ) ) (
249+ span ) ;
246250 }
247251 } ;
248252 } ;
@@ -254,7 +258,7 @@ export class HttpPlugin extends classes.BasePlugin {
254258 * @param original The original patched function.
255259 * @param options The arguments to the original function.
256260 */
257- private makeRequestTrace (
261+ private getMakeRequestTraceFunction (
258262 // tslint:disable-next-line:no-any
259263 request : httpModule . ClientRequest , options : httpModule . RequestOptions ,
260264 plugin : HttpPlugin ) : types . Func < httpModule . ClientRequest > {
@@ -300,7 +304,7 @@ export class HttpPlugin extends classes.BasePlugin {
300304 HttpPlugin . ATTRIBUTE_HTTP_STATUS_CODE ,
301305 response . statusCode . toString ( ) ) ;
302306
303- span . status = plugin . traceStatus ( response . statusCode ) ;
307+ span . status = HttpPlugin . convertTraceStatus ( response . statusCode ) ;
304308
305309 // Message Event ID is not defined
306310 span . addMessageEvent (
@@ -323,7 +327,11 @@ export class HttpPlugin extends classes.BasePlugin {
323327 } ;
324328 }
325329
326- traceStatus ( statusCode : number ) : number {
330+ /**
331+ * Converts an HTTP status code to an OpenCensus Trace status code.
332+ * @param statusCode The HTTP status code to convert.
333+ */
334+ static convertTraceStatus ( statusCode : number ) : number {
327335 if ( statusCode < 200 || statusCode > 504 ) {
328336 return TraceStatusCodes . UNKNOWN ;
329337 } else if ( statusCode >= 200 && statusCode < 400 ) {
@@ -353,6 +361,9 @@ export class HttpPlugin extends classes.BasePlugin {
353361 }
354362}
355363
364+ /**
365+ * An enumeration of OpenCensus Trace status codes.
366+ */
356367export enum TraceStatusCodes {
357368 UNKNOWN = 2 ,
358369 OK = 0 ,
0 commit comments