@@ -52,76 +52,83 @@ function instrumentationS3 (orig, origArguments, request, AWS, agent, { version,
52
52
name += ' ' + resource
53
53
}
54
54
55
- const span = agent . startSpan ( name , TYPE , SUBTYPE , opName )
56
- if ( span ) {
57
- request . on ( 'complete' , function onComplete ( response ) {
58
- // `response` is an AWS.Response
59
- // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html
60
-
61
- // Determining the bucket's region.
62
- // `request.httpRequest.region` isn't documented, but the aws-sdk@2
63
- // lib/services/s3.js will set it to the bucket's determined region.
64
- // This can be asynchronously determined -- e.g. if it differs from the
65
- // configured service endpoint region -- so this won't be set until
66
- // 'complete'.
67
- const region = request . httpRequest && request . httpRequest . region
68
-
69
- // Destination context.
70
- // '.httpRequest.endpoint' might differ from '.service.endpoint' if
71
- // the bucket is in a different region.
72
- const endpoint = request . httpRequest && request . httpRequest . endpoint
73
- const destContext = {
74
- service : {
75
- name : SUBTYPE ,
76
- type : TYPE
77
- }
78
- }
79
- if ( endpoint ) {
80
- destContext . address = endpoint . hostname
81
- destContext . port = endpoint . port
82
- }
83
- if ( resource ) {
84
- destContext . service . resource = resource
55
+ const ins = agent . _instrumentation
56
+ const span = ins . currTx ( ) . startSpan ( name , TYPE , SUBTYPE , opName )
57
+ if ( ! span ) {
58
+ return orig . apply ( request , origArguments )
59
+ }
60
+
61
+ function onComplete ( response ) {
62
+ // `response` is an AWS.Response
63
+ // https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Response.html
64
+
65
+ // Determining the bucket's region.
66
+ // `request.httpRequest.region` isn't documented, but the aws-sdk@2
67
+ // lib/services/s3.js will set it to the bucket's determined region.
68
+ // This can be asynchronously determined -- e.g. if it differs from the
69
+ // configured service endpoint region -- so this won't be set until
70
+ // 'complete'.
71
+ const region = request . httpRequest && request . httpRequest . region
72
+
73
+ // Destination context.
74
+ // '.httpRequest.endpoint' might differ from '.service.endpoint' if
75
+ // the bucket is in a different region.
76
+ const endpoint = request . httpRequest && request . httpRequest . endpoint
77
+ const destContext = {
78
+ service : {
79
+ name : SUBTYPE ,
80
+ type : TYPE
85
81
}
86
- if ( region ) {
87
- destContext . cloud = { region }
82
+ }
83
+ if ( endpoint ) {
84
+ destContext . address = endpoint . hostname
85
+ destContext . port = endpoint . port
86
+ }
87
+ if ( resource ) {
88
+ destContext . service . resource = resource
89
+ }
90
+ if ( region ) {
91
+ destContext . cloud = { region }
92
+ }
93
+ span . setDestinationContext ( destContext )
94
+
95
+ if ( response ) {
96
+ // Follow the spec for HTTP client span outcome.
97
+ // https://github.com/elastic/apm/blob/master/specs/agents/tracing-instrumentation-http.md#outcome
98
+ //
99
+ // For example, a S3 GetObject conditional request (e.g. using the
100
+ // IfNoneMatch param) will respond with response.error=NotModifed and
101
+ // statusCode=304. This is a *successful* outcome.
102
+ const statusCode = response . httpResponse && response . httpResponse . statusCode
103
+ if ( statusCode ) {
104
+ span . _setOutcomeFromHttpStatusCode ( statusCode )
105
+ } else {
106
+ // `statusCode` will be undefined for errors before sending a request, e.g.:
107
+ // InvalidConfiguration: Custom endpoint is not compatible with access point ARN
108
+ span . _setOutcomeFromErrorCapture ( constants . OUTCOME_FAILURE )
88
109
}
89
- span . setDestinationContext ( destContext )
90
-
91
- if ( response ) {
92
- // Follow the spec for HTTP client span outcome.
93
- // https://github.com/elastic/apm/blob/master/specs/agents/tracing-instrumentation-http.md#outcome
94
- //
95
- // For example, a S3 GetObject conditional request (e.g. using the
96
- // IfNoneMatch param) will respond with response.error=NotModifed and
97
- // statusCode=304. This is a *successful* outcome.
98
- const statusCode = response . httpResponse && response . httpResponse . statusCode
99
- if ( statusCode ) {
100
- span . _setOutcomeFromHttpStatusCode ( statusCode )
101
- } else {
102
- // `statusCode` will be undefined for errors before sending a request, e.g.:
103
- // InvalidConfiguration: Custom endpoint is not compatible with access point ARN
104
- span . _setOutcomeFromErrorCapture ( constants . OUTCOME_FAILURE )
105
- }
106
-
107
- if ( response . error && ( ! statusCode || statusCode >= 400 ) ) {
108
- agent . captureError ( response . error , { skipOutcome : true } )
109
- }
110
+
111
+ if ( response . error && ( ! statusCode || statusCode >= 400 ) ) {
112
+ agent . captureError ( response . error , { skipOutcome : true } )
110
113
}
114
+ }
111
115
112
- // Workaround a bug in the agent's handling of `span.sync`.
113
- //
114
- // The bug: Currently this span.sync is not set `false` because there is
115
- // an HTTP span created (for this S3 request) in the same async op. That
116
- // HTTP span becomes the "active span" for this async op, and *it* gets
117
- // marked as sync=false in `before()` in async-hooks.js.
118
- span . sync = false
119
-
120
- span . end ( )
121
- } )
116
+ // Workaround a bug in the agent's handling of `span.sync`.
117
+ //
118
+ // The bug: Currently this span.sync is not set `false` because there is
119
+ // an HTTP span created (for this S3 request) in the same async op. That
120
+ // HTTP span becomes the "active span" for this async op, and *it* gets
121
+ // marked as sync=false in `before()` in async-hooks.js.
122
+ span . sync = false
123
+
124
+ span . end ( )
122
125
}
123
126
124
- return orig . apply ( request , origArguments )
127
+ // Derive a new run context from the current one for this span. Then run
128
+ // the AWS.Request.send and a 'complete' event handler in that run context.
129
+ const runContext = ins . _runCtxMgr . active ( ) . enterSpan ( span ) // XXX I don't like `enterSpan` name here, perhaps `newWithSpan()`?
130
+ request . on ( 'complete' , ins . _runCtxMgr . bind ( runContext , onComplete ) )
131
+ return ins . _runCtxMgr . with ( runContext , orig , request , ...origArguments )
125
132
}
126
133
127
134
module . exports = {
0 commit comments