dd-trace 2.7.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/datadog-instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/aws-sdk.js +104 -0
- package/packages/datadog-instrumentations/src/fastify.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/base.js +146 -0
- package/packages/datadog-plugin-aws-sdk/src/index.js +16 -106
- package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +4 -2
- package/packages/datadog-plugin-aws-sdk/src/services/default.js +7 -0
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +3 -1
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +5 -4
- package/packages/datadog-plugin-aws-sdk/src/services/index.js +12 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -3
- package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +4 -3
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -1
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -1
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +4 -3
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +45 -6
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/datadog-plugin-aws-sdk/src/helpers.js +0 -103
package/package.json
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
function wrapRequest (send) {
|
|
11
|
+
return function wrappedRequest (cb) {
|
|
12
|
+
if (!this.service) return send.apply(this, arguments)
|
|
13
|
+
|
|
14
|
+
const serviceIdentifier = this.service.serviceIdentifier
|
|
15
|
+
const channelSuffix = getChannelSuffix(serviceIdentifier)
|
|
16
|
+
const startCh = channel(`apm:aws:request:start:${channelSuffix}`)
|
|
17
|
+
if (!startCh.hasSubscribers) return send.apply(this, arguments)
|
|
18
|
+
const outerAr = new AsyncResource('apm:aws:request:outer')
|
|
19
|
+
|
|
20
|
+
this.on('complete', response => {
|
|
21
|
+
channel(`apm:aws:request:complete:${channelSuffix}`).publish({ response })
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
return new AsyncResource('apm:aws:request:inner').runInAsyncScope(() => {
|
|
25
|
+
startCh.publish({
|
|
26
|
+
serviceIdentifier,
|
|
27
|
+
operation: this.operation,
|
|
28
|
+
awsRegion: this.service.config && this.service.config.region,
|
|
29
|
+
awsService: this.service.api && this.service.api.className,
|
|
30
|
+
request: this
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
if (typeof cb === 'function') {
|
|
34
|
+
arguments[0] = wrapCb(cb, channelSuffix, this, outerAr)
|
|
35
|
+
}
|
|
36
|
+
return send.apply(this, arguments)
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function wrapCb (cb, serviceName, request, ar) {
|
|
42
|
+
return function wrappedCb (err, response) {
|
|
43
|
+
const obj = { request, response }
|
|
44
|
+
return ar.runInAsyncScope(() => {
|
|
45
|
+
channel(`apm:aws:response:start:${serviceName}`).publish(obj)
|
|
46
|
+
// TODO(bengl) make this work without needing a needsFinish property added to the object
|
|
47
|
+
if (!obj.needsFinish) {
|
|
48
|
+
return cb.apply(this, arguments)
|
|
49
|
+
}
|
|
50
|
+
const finishChannel = channel(`apm:aws:response:finish:${serviceName}`)
|
|
51
|
+
try {
|
|
52
|
+
let result = cb.apply(this, arguments)
|
|
53
|
+
if (result && result.then) {
|
|
54
|
+
result = result.then(x => {
|
|
55
|
+
finishChannel.publish()
|
|
56
|
+
return x
|
|
57
|
+
}, e => {
|
|
58
|
+
finishChannel.publish(e)
|
|
59
|
+
throw e
|
|
60
|
+
})
|
|
61
|
+
} else {
|
|
62
|
+
finishChannel.publish()
|
|
63
|
+
}
|
|
64
|
+
return result
|
|
65
|
+
} catch (e) {
|
|
66
|
+
finishChannel.publish(e)
|
|
67
|
+
throw e
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function getChannelSuffix (name) {
|
|
74
|
+
return [
|
|
75
|
+
'cloudwatchlogs',
|
|
76
|
+
'dynamodb',
|
|
77
|
+
'eventbridge',
|
|
78
|
+
'kinesis',
|
|
79
|
+
'lambda',
|
|
80
|
+
'redshift',
|
|
81
|
+
's3',
|
|
82
|
+
'sns',
|
|
83
|
+
'sqs'
|
|
84
|
+
].includes(name) ? name : 'default'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
|
|
88
|
+
shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
|
|
89
|
+
shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
|
|
90
|
+
return function wrappedSetPromisesDependency (dep) {
|
|
91
|
+
const result = setPromisesDependency.apply(this, arguments)
|
|
92
|
+
shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
|
|
93
|
+
return result
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
return AWS
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// <2.1.35 has breaking changes for instrumentation
|
|
100
|
+
// https://github.com/aws/aws-sdk-js/pull/629
|
|
101
|
+
addHook({ name: 'aws-sdk', versions: ['>=2.1.35'] }, AWS => {
|
|
102
|
+
shimmer.wrap(AWS.Request.prototype, 'send', wrapRequest)
|
|
103
|
+
return AWS
|
|
104
|
+
})
|
|
@@ -45,7 +45,7 @@ function wrapAddHook (addHook) {
|
|
|
45
45
|
|
|
46
46
|
if (!requestResource) return fn.apply(this, arguments)
|
|
47
47
|
|
|
48
|
-
requestResource.runInAsyncScope(() => {
|
|
48
|
+
return requestResource.runInAsyncScope(() => {
|
|
49
49
|
const hookResource = new AsyncResource('bound-anonymous-fn')
|
|
50
50
|
|
|
51
51
|
try {
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Tags = require('opentracing').Tags
|
|
4
|
+
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
5
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
6
|
+
const { storage } = require('../../datadog-core')
|
|
7
|
+
|
|
8
|
+
class BaseAwsSdkPlugin extends Plugin {
|
|
9
|
+
get serviceIdentifier () {
|
|
10
|
+
const id = this.constructor.name.toLowerCase()
|
|
11
|
+
Object.defineProperty(this, 'serviceIdentifier', {
|
|
12
|
+
configurable: true,
|
|
13
|
+
writable: true,
|
|
14
|
+
enumerable: true,
|
|
15
|
+
value: id
|
|
16
|
+
})
|
|
17
|
+
return id
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
constructor (...args) {
|
|
21
|
+
super(...args)
|
|
22
|
+
|
|
23
|
+
this.addSub(`apm:aws:request:start:${this.serviceIdentifier}`, ({
|
|
24
|
+
request,
|
|
25
|
+
operation,
|
|
26
|
+
awsRegion,
|
|
27
|
+
awsService,
|
|
28
|
+
serviceIdentifier
|
|
29
|
+
}) => {
|
|
30
|
+
if (!this.isEnabled(request)) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
const serviceName = this.getServiceName(serviceIdentifier)
|
|
34
|
+
const childOf = this.tracer.scope().active()
|
|
35
|
+
const tags = {
|
|
36
|
+
[Tags.SPAN_KIND]: 'client',
|
|
37
|
+
'service.name': serviceName,
|
|
38
|
+
'aws.operation': operation,
|
|
39
|
+
'aws.region': awsRegion,
|
|
40
|
+
'aws.service': awsService,
|
|
41
|
+
'component': 'aws-sdk'
|
|
42
|
+
}
|
|
43
|
+
if (this.requestTags) this.requestTags.set(request, tags)
|
|
44
|
+
|
|
45
|
+
const span = this.tracer.startSpan('aws.request', { childOf, tags })
|
|
46
|
+
|
|
47
|
+
analyticsSampler.sample(span, this.config.measured)
|
|
48
|
+
|
|
49
|
+
this.requestInject(span, request)
|
|
50
|
+
|
|
51
|
+
const store = storage.getStore()
|
|
52
|
+
|
|
53
|
+
this.enter(span, store)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
this.addSub(`apm:aws:request:complete:${this.serviceIdentifier}`, ({ response }) => {
|
|
57
|
+
const store = storage.getStore()
|
|
58
|
+
if (!store) return
|
|
59
|
+
const { span } = store
|
|
60
|
+
if (!span) return
|
|
61
|
+
this.addResponseTags(span, response)
|
|
62
|
+
this.finish(span, response, response.error)
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
requestInject (span, request) {
|
|
67
|
+
// implemented by subclasses, or not
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
isEnabled (request) {
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
addResponseTags (span, response) {
|
|
75
|
+
if (!span || !response.request) return
|
|
76
|
+
const params = response.request.params
|
|
77
|
+
const operation = response.request.operation
|
|
78
|
+
const extraTags = this.generateTags(params, operation, response) || {}
|
|
79
|
+
const tags = Object.assign({
|
|
80
|
+
'aws.response.request_id': response.requestId,
|
|
81
|
+
'resource.name': operation,
|
|
82
|
+
'span.kind': 'client'
|
|
83
|
+
}, extraTags)
|
|
84
|
+
|
|
85
|
+
span.addTags(tags)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
generateTags () {
|
|
89
|
+
// implemented by subclasses, or not
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
finish (span, response, err) {
|
|
93
|
+
if (err) {
|
|
94
|
+
span.setTag('error', err)
|
|
95
|
+
|
|
96
|
+
if (err.requestId) {
|
|
97
|
+
span.addTags({ 'aws.response.request_id': err.requestId })
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (response) {
|
|
102
|
+
this.config.hooks.request(span, response)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
span.finish()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
configure (config) {
|
|
109
|
+
super.configure(normalizeConfig(config, this.serviceIdentifier))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// TODO: test splitByAwsService when the test suite is fixed
|
|
113
|
+
getServiceName (serviceIdentifier) {
|
|
114
|
+
return this.config.service
|
|
115
|
+
? this.config.service
|
|
116
|
+
: `${this.tracer._service}-aws-${serviceIdentifier}`
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function normalizeConfig (config, serviceIdentifier) {
|
|
121
|
+
const hooks = getHooks(config)
|
|
122
|
+
|
|
123
|
+
let specificConfig = config[serviceIdentifier]
|
|
124
|
+
switch (typeof specificConfig) {
|
|
125
|
+
case 'undefined':
|
|
126
|
+
specificConfig = {}
|
|
127
|
+
break
|
|
128
|
+
case 'boolean':
|
|
129
|
+
specificConfig = { enabled: specificConfig }
|
|
130
|
+
break
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return Object.assign({}, config, specificConfig, {
|
|
134
|
+
splitByAwsService: config.splitByAwsService !== false,
|
|
135
|
+
hooks
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function getHooks (config) {
|
|
140
|
+
const noop = () => {}
|
|
141
|
+
const request = (config.hooks && config.hooks.request) || noop
|
|
142
|
+
|
|
143
|
+
return { request }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = BaseAwsSdkPlugin
|
|
@@ -1,118 +1,28 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
5
|
-
const awsHelpers = require('./helpers')
|
|
3
|
+
const Plugin = require('../../dd-trace/src/plugins/plugin')
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
config = normalizeConfig(config)
|
|
9
|
-
return function wrapRequest (send) {
|
|
10
|
-
return function requestWithTrace (cb) {
|
|
11
|
-
if (!this.service) return send.apply(this, arguments)
|
|
5
|
+
const services = require('./services')
|
|
12
6
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const serviceName = getServiceName(serviceIdentifier, tracer, config)
|
|
20
|
-
const childOf = tracer.scope().active()
|
|
21
|
-
const tags = {
|
|
22
|
-
[Tags.SPAN_KIND]: 'client',
|
|
23
|
-
'service.name': serviceName,
|
|
24
|
-
'aws.operation': this.operation,
|
|
25
|
-
'aws.region': this.service.config && this.service.config.region,
|
|
26
|
-
'aws.service': this.service.api && this.service.api.className,
|
|
27
|
-
'component': 'aws-sdk'
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const span = tracer.startSpan('aws.request', {
|
|
31
|
-
childOf,
|
|
32
|
-
tags
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
this.on('complete', response => {
|
|
36
|
-
if (!span) return
|
|
37
|
-
|
|
38
|
-
awsHelpers.addResponseTags(span, response, serviceIdentifier, config, tracer)
|
|
39
|
-
awsHelpers.finish(config, span, response, response.error)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
analyticsSampler.sample(span, config.measured)
|
|
43
|
-
|
|
44
|
-
awsHelpers.requestInject(span, this, serviceIdentifier, tracer)
|
|
45
|
-
|
|
46
|
-
const request = this
|
|
7
|
+
class AwsSdkPlugin extends Plugin {
|
|
8
|
+
static get name () {
|
|
9
|
+
return 'aws-sdk'
|
|
10
|
+
}
|
|
47
11
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
12
|
+
constructor (...args) {
|
|
13
|
+
super(...args)
|
|
14
|
+
this.services = {}
|
|
15
|
+
for (const name in services) {
|
|
16
|
+
const ServicePlugin = services[name]
|
|
17
|
+
this.services[name] = new ServicePlugin(...args)
|
|
54
18
|
}
|
|
55
19
|
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function createWrapSetPromisesDependency (tracer, config, instrumenter, AWS) {
|
|
59
|
-
return function wrapSetPromisesDependency (setPromisesDependency) {
|
|
60
|
-
return function setPromisesDependencyWithTrace (dep) {
|
|
61
|
-
const result = setPromisesDependency.apply(this, arguments)
|
|
62
|
-
|
|
63
|
-
instrumenter.wrap(AWS.Request.prototype, 'promise', createWrapRequest(tracer, config))
|
|
64
20
|
|
|
65
|
-
|
|
21
|
+
configure (config) {
|
|
22
|
+
for (const service of Object.values(this.services)) {
|
|
23
|
+
service.configure(config)
|
|
66
24
|
}
|
|
67
25
|
}
|
|
68
26
|
}
|
|
69
27
|
|
|
70
|
-
|
|
71
|
-
const hooks = getHooks(config)
|
|
72
|
-
|
|
73
|
-
return Object.assign({}, config, {
|
|
74
|
-
splitByAwsService: config.splitByAwsService !== false,
|
|
75
|
-
hooks
|
|
76
|
-
})
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function getHooks (config) {
|
|
80
|
-
const noop = () => {}
|
|
81
|
-
const request = (config.hooks && config.hooks.request) || noop
|
|
82
|
-
|
|
83
|
-
return { request }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// TODO: test splitByAwsService when the test suite is fixed
|
|
87
|
-
function getServiceName (serviceIdentifier, tracer, config) {
|
|
88
|
-
return config.service
|
|
89
|
-
? config.service
|
|
90
|
-
: `${tracer._service}-aws-${serviceIdentifier}`
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// <2.1.35 has breaking changes for instrumentation
|
|
94
|
-
// https://github.com/aws/aws-sdk-js/pull/629
|
|
95
|
-
module.exports = [
|
|
96
|
-
{
|
|
97
|
-
name: 'aws-sdk',
|
|
98
|
-
versions: ['>=2.3.0'],
|
|
99
|
-
patch (AWS, tracer, config) {
|
|
100
|
-
this.wrap(AWS.Request.prototype, 'promise', createWrapRequest(tracer, config))
|
|
101
|
-
this.wrap(AWS.config, 'setPromisesDependency', createWrapSetPromisesDependency(tracer, config, this, AWS))
|
|
102
|
-
},
|
|
103
|
-
unpatch (AWS) {
|
|
104
|
-
this.unwrap(AWS.Request.prototype, 'promise')
|
|
105
|
-
this.unwrap(AWS.config, 'setPromisesDependency')
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
name: 'aws-sdk',
|
|
110
|
-
versions: ['>=2.1.35'],
|
|
111
|
-
patch (AWS, tracer, config) {
|
|
112
|
-
this.wrap(AWS.Request.prototype, 'send', createWrapRequest(tracer, config))
|
|
113
|
-
},
|
|
114
|
-
unpatch (AWS) {
|
|
115
|
-
this.unwrap(AWS.Request.prototype, 'send')
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
]
|
|
28
|
+
module.exports = AwsSdkPlugin
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
4
|
+
|
|
5
|
+
class CloudwatchLogs extends BaseAwsSdkPlugin {
|
|
6
|
+
generateTags (params, operation) {
|
|
5
7
|
const tags = {}
|
|
6
8
|
|
|
7
9
|
if (!params || !params.logGroupName) return tags
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const log = require('../../../dd-trace/src/log')
|
|
3
|
-
|
|
3
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
4
|
+
|
|
5
|
+
class EventBridge extends BaseAwsSdkPlugin {
|
|
4
6
|
generateTags (params, operation, response) {
|
|
5
7
|
if (!params || !params.source) return {}
|
|
6
8
|
|
|
@@ -14,14 +16,13 @@ class EventBridge {
|
|
|
14
16
|
* requestInject
|
|
15
17
|
* @param {*} span
|
|
16
18
|
* @param {*} request
|
|
17
|
-
* @param {*} tracer
|
|
18
19
|
*
|
|
19
20
|
* Docs: https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEventsRequestEntry.html
|
|
20
21
|
* We cannot use the traceHeader field as that's reserved for X-Ray.
|
|
21
22
|
* Detail must be a valid JSON string
|
|
22
23
|
* Max size per event is 256kb (https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevent-size.html)
|
|
23
24
|
*/
|
|
24
|
-
requestInject (span, request
|
|
25
|
+
requestInject (span, request) {
|
|
25
26
|
const operation = request.operation
|
|
26
27
|
if (operation === 'putEvents' &&
|
|
27
28
|
request.params &&
|
|
@@ -31,7 +32,7 @@ class EventBridge {
|
|
|
31
32
|
try {
|
|
32
33
|
const details = JSON.parse(request.params.Entries[0].Detail)
|
|
33
34
|
details._datadog = {}
|
|
34
|
-
tracer.inject(span, 'text_map', details._datadog)
|
|
35
|
+
this.tracer.inject(span, 'text_map', details._datadog)
|
|
35
36
|
const finalData = JSON.stringify(details)
|
|
36
37
|
const byteSize = Buffer.byteLength(finalData)
|
|
37
38
|
if (byteSize >= (1024 * 256)) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
exports.cloudwatchlogs = require('./cloudwatchlogs')
|
|
4
|
+
exports.dynamodb = require('./dynamodb')
|
|
5
|
+
exports.eventbridge = require('./eventbridge')
|
|
6
|
+
exports.kinesis = require('./kinesis')
|
|
7
|
+
exports.lambda = require('./lambda')
|
|
8
|
+
exports.redshift = require('./redshift')
|
|
9
|
+
exports.s3 = require('./s3')
|
|
10
|
+
exports.sns = require('./sns')
|
|
11
|
+
exports.sqs = require('./sqs')
|
|
12
|
+
exports.default = require('./default')
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const log = require('../../../dd-trace/src/log')
|
|
3
|
-
|
|
3
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
4
|
+
class Kinesis extends BaseAwsSdkPlugin {
|
|
4
5
|
generateTags (params, operation, response) {
|
|
5
6
|
if (!params || !params.StreamName) return {}
|
|
6
7
|
|
|
@@ -26,7 +27,7 @@ class Kinesis {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
requestInject (span, request
|
|
30
|
+
requestInject (span, request) {
|
|
30
31
|
const operation = request.operation
|
|
31
32
|
if (operation === 'putRecord' || operation === 'putRecords') {
|
|
32
33
|
if (!request.params) {
|
|
@@ -34,7 +35,7 @@ class Kinesis {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
const traceData = {}
|
|
37
|
-
tracer.inject(span, 'text_map', traceData)
|
|
38
|
+
this.tracer.inject(span, 'text_map', traceData)
|
|
38
39
|
let injectPath
|
|
39
40
|
if (request.params.Records && request.params.Records.length > 0) {
|
|
40
41
|
injectPath = request.params.Records[0]
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const log = require('../../../dd-trace/src/log')
|
|
4
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
4
5
|
|
|
5
|
-
class Lambda {
|
|
6
|
+
class Lambda extends BaseAwsSdkPlugin {
|
|
6
7
|
generateTags (params, operation, response) {
|
|
7
8
|
const tags = {}
|
|
8
9
|
|
|
@@ -14,7 +15,7 @@ class Lambda {
|
|
|
14
15
|
})
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
requestInject (span, request
|
|
18
|
+
requestInject (span, request) {
|
|
18
19
|
const operation = request.operation
|
|
19
20
|
if (operation === 'invoke') {
|
|
20
21
|
if (!request.params) {
|
|
@@ -35,7 +36,7 @@ class Lambda {
|
|
|
35
36
|
if (!clientContext.custom) {
|
|
36
37
|
clientContext.custom = {}
|
|
37
38
|
}
|
|
38
|
-
tracer.inject(span, 'text_map', clientContext.custom)
|
|
39
|
+
this.tracer.inject(span, 'text_map', clientContext.custom)
|
|
39
40
|
const newContextBase64 = Buffer.from(JSON.stringify(clientContext)).toString('base64')
|
|
40
41
|
request.params.ClientContext = newContextBase64
|
|
41
42
|
} catch (err) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const log = require('../../../dd-trace/src/log')
|
|
3
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
3
4
|
|
|
4
|
-
class Sns {
|
|
5
|
+
class Sns extends BaseAwsSdkPlugin {
|
|
5
6
|
generateTags (params, operation, response) {
|
|
6
7
|
if (!params) return {}
|
|
7
8
|
|
|
@@ -16,7 +17,7 @@ class Sns {
|
|
|
16
17
|
// for example if it contains a phone number?
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
requestInject (span, request
|
|
20
|
+
requestInject (span, request) {
|
|
20
21
|
const operation = request.operation
|
|
21
22
|
if (operation === 'publish' || operation === 'publishBatch') {
|
|
22
23
|
if (!request.params) {
|
|
@@ -36,7 +37,7 @@ class Sns {
|
|
|
36
37
|
return
|
|
37
38
|
}
|
|
38
39
|
const ddInfo = {}
|
|
39
|
-
tracer.inject(span, 'text_map', ddInfo)
|
|
40
|
+
this.tracer.inject(span, 'text_map', ddInfo)
|
|
40
41
|
injectPath.MessageAttributes._datadog = {
|
|
41
42
|
DataType: 'Binary',
|
|
42
43
|
BinaryValue: JSON.stringify(ddInfo) // BINARY types are automatically base64 encoded
|
|
@@ -1,9 +1,48 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const Tags = require('opentracing').Tags
|
|
3
4
|
const log = require('../../../dd-trace/src/log')
|
|
5
|
+
const BaseAwsSdkPlugin = require('../base')
|
|
6
|
+
const { storage } = require('../../../datadog-core')
|
|
4
7
|
|
|
5
|
-
class Sqs {
|
|
6
|
-
|
|
8
|
+
class Sqs extends BaseAwsSdkPlugin {
|
|
9
|
+
constructor (...args) {
|
|
10
|
+
super(...args)
|
|
11
|
+
//
|
|
12
|
+
// TODO(bengl) Find a way to create the response span tags without this WeakMap being populated
|
|
13
|
+
// in the base class
|
|
14
|
+
this.requestTags = new WeakMap()
|
|
15
|
+
|
|
16
|
+
this.addSub('apm:aws:response:start:sqs', obj => {
|
|
17
|
+
const { request, response } = obj
|
|
18
|
+
const store = storage.getStore()
|
|
19
|
+
const plugin = this
|
|
20
|
+
const maybeChildOf = this.responseExtract(request.params, request.operation, response)
|
|
21
|
+
if (maybeChildOf) {
|
|
22
|
+
obj.needsFinish = true
|
|
23
|
+
const options = {
|
|
24
|
+
childOf: maybeChildOf,
|
|
25
|
+
tags: Object.assign(
|
|
26
|
+
{},
|
|
27
|
+
this.requestTags.get(request) || {},
|
|
28
|
+
{ [Tags.SPAN_KIND]: 'server' }
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
const span = plugin.tracer.startSpan('aws.response', options)
|
|
32
|
+
this.enter(span, store)
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
this.addSub('apm:aws:response:finish:sqs', err => {
|
|
37
|
+
const { span } = storage.getStore()
|
|
38
|
+
this.finish(span, null, err)
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
isEnabled (request) {
|
|
43
|
+
// TODO(bengl) Figure out a way to make separate plugins for consumer and producer so that
|
|
44
|
+
// config can be isolated to `.configure()` instead of this whole isEnabled() thing.
|
|
45
|
+
const config = this.config
|
|
7
46
|
switch (request.operation) {
|
|
8
47
|
case 'receiveMessage':
|
|
9
48
|
return config.consumer !== false
|
|
@@ -39,7 +78,7 @@ class Sqs {
|
|
|
39
78
|
return tags
|
|
40
79
|
}
|
|
41
80
|
|
|
42
|
-
responseExtract (params, operation, response
|
|
81
|
+
responseExtract (params, operation, response) {
|
|
43
82
|
if (operation === 'receiveMessage') {
|
|
44
83
|
if (
|
|
45
84
|
(!params.MaxNumberOfMessages || params.MaxNumberOfMessages === 1) &&
|
|
@@ -52,7 +91,7 @@ class Sqs {
|
|
|
52
91
|
) {
|
|
53
92
|
const textMap = response.Messages[0].MessageAttributes._datadog.StringValue
|
|
54
93
|
try {
|
|
55
|
-
return tracer.extract('text_map', JSON.parse(textMap))
|
|
94
|
+
return this.tracer.extract('text_map', JSON.parse(textMap))
|
|
56
95
|
} catch (err) {
|
|
57
96
|
log.error(err)
|
|
58
97
|
return undefined
|
|
@@ -61,7 +100,7 @@ class Sqs {
|
|
|
61
100
|
}
|
|
62
101
|
}
|
|
63
102
|
|
|
64
|
-
requestInject (span, request
|
|
103
|
+
requestInject (span, request) {
|
|
65
104
|
const operation = request.operation
|
|
66
105
|
if (operation === 'sendMessage') {
|
|
67
106
|
if (!request.params) {
|
|
@@ -74,7 +113,7 @@ class Sqs {
|
|
|
74
113
|
return
|
|
75
114
|
}
|
|
76
115
|
const ddInfo = {}
|
|
77
|
-
tracer.inject(span, 'text_map', ddInfo)
|
|
116
|
+
this.tracer.inject(span, 'text_map', ddInfo)
|
|
78
117
|
request.params.MessageAttributes._datadog = {
|
|
79
118
|
DataType: 'String',
|
|
80
119
|
StringValue: JSON.stringify(ddInfo)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = '2.7.
|
|
1
|
+
module.exports = '2.7.1'
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const Tags = require('opentracing').Tags
|
|
4
|
-
|
|
5
|
-
const services = {
|
|
6
|
-
cloudwatchlogs: getService(require('./services/cloudwatchlogs')),
|
|
7
|
-
dynamodb: getService(require('./services/dynamodb')),
|
|
8
|
-
kinesis: getService(require('./services/kinesis')),
|
|
9
|
-
lambda: getService(require('./services/lambda')),
|
|
10
|
-
s3: getService(require('./services/s3')),
|
|
11
|
-
redshift: getService(require('./services/redshift')),
|
|
12
|
-
sns: getService(require('./services/sns')),
|
|
13
|
-
sqs: getService(require('./services/sqs')),
|
|
14
|
-
eventbridge: getService(require('./services/eventbridge'))
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function getService (Service) {
|
|
18
|
-
return new Service()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const helpers = {
|
|
22
|
-
finish (config, span, response, err) {
|
|
23
|
-
if (err) {
|
|
24
|
-
span.setTag('error', err)
|
|
25
|
-
|
|
26
|
-
if (err.requestId) {
|
|
27
|
-
span.addTags({ 'aws.response.request_id': err.requestId })
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
config.hooks.request(span, response)
|
|
32
|
-
|
|
33
|
-
span.finish()
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
isEnabled (serviceIdentifier, config, request) {
|
|
37
|
-
if (typeof config === 'boolean') {
|
|
38
|
-
return config
|
|
39
|
-
} else if (!config || typeof config !== 'object' || !services[serviceIdentifier]) {
|
|
40
|
-
return true
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return services[serviceIdentifier].isEnabled
|
|
44
|
-
? services[serviceIdentifier].isEnabled(config, request)
|
|
45
|
-
: true
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
addResponseTags (span, response, serviceName) {
|
|
49
|
-
if (!span) return
|
|
50
|
-
|
|
51
|
-
if (response.request) {
|
|
52
|
-
this.addServicesTags(span, response, serviceName)
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
addServicesTags (span, response, serviceName) {
|
|
57
|
-
if (!span) return
|
|
58
|
-
|
|
59
|
-
const params = response.request.params
|
|
60
|
-
const operation = response.request.operation
|
|
61
|
-
const extraTags = services[serviceName] ? services[serviceName].generateTags(params, operation, response) : {}
|
|
62
|
-
const tags = Object.assign({
|
|
63
|
-
'aws.response.request_id': response.requestId,
|
|
64
|
-
'resource.name': operation,
|
|
65
|
-
'span.kind': 'client'
|
|
66
|
-
}, extraTags)
|
|
67
|
-
|
|
68
|
-
span.addTags(tags)
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
responseExtract (serviceName, request, response, tracer) {
|
|
72
|
-
if (services[serviceName] && services[serviceName].responseExtract) {
|
|
73
|
-
const params = request.params
|
|
74
|
-
const operation = request.operation
|
|
75
|
-
return services[serviceName].responseExtract(params, operation, response, tracer)
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
requestInject (span, request, serviceName, tracer) {
|
|
80
|
-
if (!span) return
|
|
81
|
-
|
|
82
|
-
const service = services[serviceName] && services[serviceName]
|
|
83
|
-
if (service && service.requestInject) service.requestInject(span, request, tracer)
|
|
84
|
-
},
|
|
85
|
-
|
|
86
|
-
wrapCb (cb, serviceName, tags, request, tracer, childOf) {
|
|
87
|
-
const awsHelpers = this
|
|
88
|
-
return function wrappedCb (err, resp) {
|
|
89
|
-
const maybeChildOf = awsHelpers.responseExtract(serviceName, request, resp, tracer)
|
|
90
|
-
if (maybeChildOf) {
|
|
91
|
-
const options = {
|
|
92
|
-
childOf: maybeChildOf,
|
|
93
|
-
tags: Object.assign({}, tags, { [Tags.SPAN_KIND]: 'server' })
|
|
94
|
-
}
|
|
95
|
-
return tracer.wrap('aws.response', options, cb).apply(this, arguments)
|
|
96
|
-
} else {
|
|
97
|
-
return tracer.scope().bind(cb, childOf).apply(this, arguments)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
module.exports = helpers
|