dd-trace 2.0.0 → 2.2.0
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/index.d.ts +22 -0
- package/package.json +2 -2
- package/packages/datadog-instrumentations/index.js +6 -3
- package/packages/datadog-instrumentations/src/couchbase.js +143 -0
- package/packages/datadog-instrumentations/src/elasticsearch.js +74 -0
- package/packages/datadog-instrumentations/src/mysql.js +2 -2
- package/packages/datadog-instrumentations/src/mysql2.js +76 -0
- package/packages/datadog-instrumentations/src/q.js +9 -1
- package/packages/datadog-plugin-aws-sdk/src/helpers.js +4 -3
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +48 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +56 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +33 -6
- package/packages/datadog-plugin-couchbase/src/index.js +51 -148
- package/packages/datadog-plugin-elasticsearch/src/index.js +41 -82
- package/packages/datadog-plugin-fastify/src/fastify.js +22 -1
- package/packages/datadog-plugin-mysql/src/index.js +4 -4
- package/packages/datadog-plugin-mysql2/src/index.js +5 -88
- package/packages/datadog-plugin-next/src/index.js +10 -6
- package/packages/datadog-plugin-winston/src/index.js +33 -12
- package/packages/dd-trace/lib/version.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +4 -0
- package/packages/dd-trace/src/appsec/recommended.json +5708 -1
- package/packages/dd-trace/src/profiling/config.js +5 -1
- package/packages/dd-trace/src/profiling/profiler.js +15 -6
- package/packages/dd-trace/src/profiling/profilers/cpu.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/heap.js +3 -2
- package/packages/dd-trace/src/tagger.js +14 -21
- package/packages/dd-trace/src/tracer.js +1 -1
- package/scripts/publish_docs.js +1 -1
- package/NOTICE +0 -4
- package/packages/dd-trace/src/profiling/mapper.js +0 -91
package/index.d.ts
CHANGED
|
@@ -406,6 +406,28 @@ export declare interface TracerOptions {
|
|
|
406
406
|
* @default true
|
|
407
407
|
*/
|
|
408
408
|
orphanable?: boolean
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Configuration of the AppSec protection. Can be a boolean as an alias to `appsec.enabled`.
|
|
412
|
+
*/
|
|
413
|
+
appsec?: boolean | {
|
|
414
|
+
/**
|
|
415
|
+
* Whether to enable AppSec.
|
|
416
|
+
* @default false
|
|
417
|
+
*/
|
|
418
|
+
enabled?: boolean,
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Specifies a path to a custom rules file.
|
|
422
|
+
*/
|
|
423
|
+
rules?: string,
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Controls the maximum amount of traces sampled by AppSec attacks, per second.
|
|
427
|
+
* @default 100
|
|
428
|
+
*/
|
|
429
|
+
rateLimit?: number
|
|
430
|
+
};
|
|
409
431
|
}
|
|
410
432
|
|
|
411
433
|
/** @hidden */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"node": ">=12"
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"@datadog/native-appsec": "^0.8.
|
|
64
|
+
"@datadog/native-appsec": "^0.8.1",
|
|
65
65
|
"@datadog/native-metrics": "^1.1.0",
|
|
66
66
|
"@datadog/pprof": "^0.3.0",
|
|
67
67
|
"@datadog/sketches-js": "^1.0.4",
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
require('./src/bluebird')
|
|
4
|
+
require('./src/couchbase')
|
|
3
5
|
require('./src/dns')
|
|
6
|
+
require('./src/elasticsearch')
|
|
4
7
|
require('./src/memcached')
|
|
5
8
|
require('./src/mysql')
|
|
6
|
-
require('./src/
|
|
7
|
-
require('./src/when')
|
|
9
|
+
require('./src/mysql2')
|
|
8
10
|
require('./src/promise')
|
|
9
|
-
require('./src/q')
|
|
10
11
|
require('./src/promise-js')
|
|
12
|
+
require('./src/q')
|
|
13
|
+
require('./src/when')
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Bucket => {
|
|
11
|
+
const startCh = channel('apm:couchbase:query:start')
|
|
12
|
+
const asyncEndCh = channel('apm:couchbase:query:async-end')
|
|
13
|
+
const endCh = channel('apm:couchbase:query:end')
|
|
14
|
+
const errorCh = channel('apm:couchbase:query:error')
|
|
15
|
+
|
|
16
|
+
Bucket.prototype._maybeInvoke = wrapMaybeInvoke(Bucket.prototype._maybeInvoke)
|
|
17
|
+
Bucket.prototype.query = wrapQuery(Bucket.prototype.query)
|
|
18
|
+
|
|
19
|
+
shimmer.wrap(Bucket.prototype, '_n1qlReq', _n1qlReq => function (host, q, adhoc, emitter) {
|
|
20
|
+
if (!startCh.hasSubscribers) {
|
|
21
|
+
return _n1qlReq.apply(this, arguments)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!emitter || !emitter.once) return _n1qlReq.apply(this, arguments)
|
|
25
|
+
|
|
26
|
+
const n1qlQuery = q && q.statement
|
|
27
|
+
|
|
28
|
+
startCh.publish({ resource: n1qlQuery, bucket: this })
|
|
29
|
+
|
|
30
|
+
emitter.once('rows', AsyncResource.bind(() => {
|
|
31
|
+
asyncEndCh.publish(undefined)
|
|
32
|
+
}))
|
|
33
|
+
|
|
34
|
+
emitter.once('error', AsyncResource.bind((error) => {
|
|
35
|
+
errorCh.publish(error)
|
|
36
|
+
asyncEndCh.publish(undefined)
|
|
37
|
+
}))
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
return _n1qlReq.apply(this, arguments)
|
|
41
|
+
} catch (err) {
|
|
42
|
+
err.stack // trigger getting the stack at the original throwing point
|
|
43
|
+
errorCh.publish(err)
|
|
44
|
+
|
|
45
|
+
throw err
|
|
46
|
+
} finally {
|
|
47
|
+
endCh.publish(undefined)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
Bucket.prototype.upsert = wrap('apm:couchbase:upsert', Bucket.prototype.upsert)
|
|
52
|
+
Bucket.prototype.insert = wrap('apm:couchbase:insert', Bucket.prototype.insert)
|
|
53
|
+
Bucket.prototype.replace = wrap('apm:couchbase:replace', Bucket.prototype.replace)
|
|
54
|
+
Bucket.prototype.append = wrap('apm:couchbase:append', Bucket.prototype.append)
|
|
55
|
+
Bucket.prototype.prepend = wrap('apm:couchbase:prepend', Bucket.prototype.prepend)
|
|
56
|
+
|
|
57
|
+
return Bucket
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Cluster => {
|
|
61
|
+
Cluster.prototype._maybeInvoke = wrapMaybeInvoke(Cluster.prototype._maybeInvoke)
|
|
62
|
+
Cluster.prototype.query = wrapQuery(Cluster.prototype.query)
|
|
63
|
+
|
|
64
|
+
return Cluster
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
function findCallbackIndex (args) {
|
|
68
|
+
for (let i = args.length - 1; i >= 2; i--) {
|
|
69
|
+
if (typeof args[i] === 'function') return i
|
|
70
|
+
}
|
|
71
|
+
return -1
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function wrapMaybeInvoke (_maybeInvoke) {
|
|
75
|
+
const wrapped = function (fn, args) {
|
|
76
|
+
if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
|
|
77
|
+
|
|
78
|
+
const callbackIndex = args.length - 1
|
|
79
|
+
const callback = args[callbackIndex]
|
|
80
|
+
|
|
81
|
+
if (callback instanceof Function) {
|
|
82
|
+
args[callbackIndex] = AsyncResource.bind(callback)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return _maybeInvoke.apply(this, arguments)
|
|
86
|
+
}
|
|
87
|
+
return shimmer.wrap(_maybeInvoke, wrapped)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function wrapQuery (query) {
|
|
91
|
+
const wrapped = function (q, params, callback) {
|
|
92
|
+
callback = AsyncResource.bind(arguments[arguments.length - 1])
|
|
93
|
+
|
|
94
|
+
if (typeof callback === 'function') {
|
|
95
|
+
arguments[arguments.length - 1] = callback
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const res = query.apply(this, arguments)
|
|
99
|
+
return res
|
|
100
|
+
}
|
|
101
|
+
return shimmer.wrap(query, wrapped)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function wrap (prefix, fn) {
|
|
105
|
+
const startCh = channel(prefix + ':start')
|
|
106
|
+
const endCh = channel(prefix + ':end')
|
|
107
|
+
const asyncEndCh = channel(prefix + ':async-end')
|
|
108
|
+
const errorCh = channel(prefix + ':error')
|
|
109
|
+
|
|
110
|
+
const wrapped = function (key, value, options, callback) {
|
|
111
|
+
if (!startCh.hasSubscribers) {
|
|
112
|
+
return fn.apply(this, arguments)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const callbackIndex = findCallbackIndex(arguments)
|
|
116
|
+
|
|
117
|
+
if (callbackIndex < 0) return fn.apply(this, arguments)
|
|
118
|
+
|
|
119
|
+
const cb = arguments[callbackIndex]
|
|
120
|
+
|
|
121
|
+
startCh.publish({ bucket: this })
|
|
122
|
+
|
|
123
|
+
arguments[callbackIndex] = function (error, result) {
|
|
124
|
+
if (error) {
|
|
125
|
+
errorCh.publish(error)
|
|
126
|
+
}
|
|
127
|
+
asyncEndCh.publish(result)
|
|
128
|
+
return cb.apply(this, arguments)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
return fn.apply(this, arguments)
|
|
133
|
+
} catch (error) {
|
|
134
|
+
error.stack // trigger getting the stack at the original throwing point
|
|
135
|
+
errorCh.publish(error)
|
|
136
|
+
|
|
137
|
+
throw error
|
|
138
|
+
} finally {
|
|
139
|
+
endCh.publish(undefined)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return shimmer.wrap(fn, wrapped)
|
|
143
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
const startCh = channel('apm:elasticsearch:query:start')
|
|
11
|
+
const asyncEndCh = channel('apm:elasticsearch:query:async-end')
|
|
12
|
+
const endCh = channel('apm:elasticsearch:query:end')
|
|
13
|
+
const errorCh = channel('apm:elasticsearch:query:error')
|
|
14
|
+
|
|
15
|
+
addHook({ name: '@elastic/elasticsearch', file: 'lib/Transport.js', versions: ['>=5.6.16'] }, Transport => {
|
|
16
|
+
shimmer.wrap(Transport.prototype, 'request', wrapRequest)
|
|
17
|
+
return Transport
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
addHook({ name: 'elasticsearch', file: 'src/lib/transport.js', versions: ['>=10'] }, Transport => {
|
|
21
|
+
shimmer.wrap(Transport.prototype, 'request', wrapRequest)
|
|
22
|
+
return Transport
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
function wrapRequest (request) {
|
|
26
|
+
return function (params, options, cb) {
|
|
27
|
+
if (!startCh.hasSubscribers) {
|
|
28
|
+
return request.apply(this, arguments)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!params) return request.apply(this, arguments)
|
|
32
|
+
|
|
33
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
34
|
+
|
|
35
|
+
startCh.publish({ params })
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const lastIndex = arguments.length - 1
|
|
39
|
+
cb = arguments[lastIndex]
|
|
40
|
+
|
|
41
|
+
if (typeof cb === 'function') {
|
|
42
|
+
cb = asyncResource.bind(cb)
|
|
43
|
+
|
|
44
|
+
arguments[lastIndex] = AsyncResource.bind(function (error) {
|
|
45
|
+
finish(params, error)
|
|
46
|
+
return cb.apply(null, arguments)
|
|
47
|
+
})
|
|
48
|
+
return request.apply(this, arguments)
|
|
49
|
+
} else {
|
|
50
|
+
const promise = request.apply(this, arguments)
|
|
51
|
+
if (promise && typeof promise.then === 'function') {
|
|
52
|
+
promise.then(() => finish(params), e => finish(params, e))
|
|
53
|
+
} else {
|
|
54
|
+
finish(params)
|
|
55
|
+
}
|
|
56
|
+
return promise
|
|
57
|
+
}
|
|
58
|
+
} catch (err) {
|
|
59
|
+
err.stack // trigger getting the stack at the original throwing point
|
|
60
|
+
errorCh.publish(err)
|
|
61
|
+
|
|
62
|
+
throw err
|
|
63
|
+
} finally {
|
|
64
|
+
endCh.publish(undefined)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function finish (params, error) {
|
|
70
|
+
if (error) {
|
|
71
|
+
errorCh.publish(error)
|
|
72
|
+
}
|
|
73
|
+
asyncEndCh.publish({ params })
|
|
74
|
+
}
|
|
@@ -20,9 +20,9 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const sql = arguments[0].sql ? arguments[0].sql : arguments[0]
|
|
23
|
-
const
|
|
23
|
+
const conf = this.config
|
|
24
24
|
|
|
25
|
-
startCh.publish(
|
|
25
|
+
startCh.publish({ sql, conf })
|
|
26
26
|
|
|
27
27
|
try {
|
|
28
28
|
const res = query.apply(this, arguments)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
channel,
|
|
5
|
+
addHook,
|
|
6
|
+
AsyncResource
|
|
7
|
+
} = require('./helpers/instrument')
|
|
8
|
+
const shimmer = require('../../datadog-shimmer')
|
|
9
|
+
|
|
10
|
+
addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connection => {
|
|
11
|
+
const startCh = channel('apm:mysql2:query:start')
|
|
12
|
+
const asyncEndCh = channel('apm:mysql2:query:async-end')
|
|
13
|
+
const endCh = channel('apm:mysql2:query:end')
|
|
14
|
+
const errorCh = channel('apm:mysql2:query:error')
|
|
15
|
+
|
|
16
|
+
shimmer.wrap(Connection.prototype, 'addCommand', addCommand => function (cmd) {
|
|
17
|
+
if (!startCh.hasSubscribers) return addCommand.apply(this, arguments)
|
|
18
|
+
|
|
19
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
20
|
+
const name = cmd && cmd.constructor && cmd.constructor.name
|
|
21
|
+
const isCommand = typeof cmd.execute === 'function'
|
|
22
|
+
const isQuery = isCommand && (name === 'Execute' || name === 'Query')
|
|
23
|
+
|
|
24
|
+
// TODO: consider supporting all commands and not just queries
|
|
25
|
+
cmd.execute = isQuery
|
|
26
|
+
? wrapExecute(cmd, cmd.execute, asyncResource, this.config)
|
|
27
|
+
: bindExecute(cmd, cmd.execute, asyncResource)
|
|
28
|
+
|
|
29
|
+
return asyncResource.bind(addCommand, this).apply(this, arguments)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
return Connection
|
|
33
|
+
|
|
34
|
+
function bindExecute (cmd, execute, asyncResource) {
|
|
35
|
+
return asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
36
|
+
if (this.onResult) {
|
|
37
|
+
this.onResult = asyncResource.bind(this.onResult)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return execute.apply(this, arguments)
|
|
41
|
+
}, cmd)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function wrapExecute (cmd, execute, asyncResource, config) {
|
|
45
|
+
return asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
46
|
+
const sql = cmd.statement ? cmd.statement.query : cmd.sql
|
|
47
|
+
|
|
48
|
+
startCh.publish({ sql, conf: config })
|
|
49
|
+
|
|
50
|
+
if (this.onResult) {
|
|
51
|
+
const onResult = asyncResource.bind(this.onResult)
|
|
52
|
+
|
|
53
|
+
this.onResult = AsyncResource.bind(function (error) {
|
|
54
|
+
if (error) {
|
|
55
|
+
errorCh.publish(error)
|
|
56
|
+
}
|
|
57
|
+
asyncEndCh.publish(undefined)
|
|
58
|
+
onResult.apply(this, arguments)
|
|
59
|
+
}, 'bound-anonymous-fn', this)
|
|
60
|
+
} else {
|
|
61
|
+
this.on('error', AsyncResource.bind(error => errorCh.publish(error)))
|
|
62
|
+
this.on('end', AsyncResource.bind(() => asyncEndCh.publish(undefined)))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.execute = execute
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
return execute.apply(this, arguments)
|
|
69
|
+
} catch (err) {
|
|
70
|
+
errorCh.publish(err)
|
|
71
|
+
} finally {
|
|
72
|
+
endCh.publish(undefined)
|
|
73
|
+
}
|
|
74
|
+
}, cmd)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
@@ -6,8 +6,16 @@ const shimmer = require('../../datadog-shimmer')
|
|
|
6
6
|
|
|
7
7
|
addHook({
|
|
8
8
|
name: 'q',
|
|
9
|
-
versions: ['
|
|
9
|
+
versions: ['1']
|
|
10
10
|
}, Q => {
|
|
11
11
|
shimmer.wrap(Q.makePromise.prototype, 'then', wrapThen)
|
|
12
12
|
return Q
|
|
13
13
|
})
|
|
14
|
+
|
|
15
|
+
addHook({
|
|
16
|
+
name: 'q',
|
|
17
|
+
versions: ['>=2']
|
|
18
|
+
}, Q => {
|
|
19
|
+
shimmer.wrap(Q.Promise.prototype, 'then', wrapThen)
|
|
20
|
+
return Q
|
|
21
|
+
})
|
|
@@ -10,7 +10,8 @@ const services = {
|
|
|
10
10
|
s3: getService(require('./services/s3')),
|
|
11
11
|
redshift: getService(require('./services/redshift')),
|
|
12
12
|
sns: getService(require('./services/sns')),
|
|
13
|
-
sqs: getService(require('./services/sqs'))
|
|
13
|
+
sqs: getService(require('./services/sqs')),
|
|
14
|
+
eventbridge: getService(require('./services/eventbridge'))
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
function getService (Service) {
|
|
@@ -78,8 +79,8 @@ const helpers = {
|
|
|
78
79
|
requestInject (span, request, serviceName, tracer) {
|
|
79
80
|
if (!span) return
|
|
80
81
|
|
|
81
|
-
const
|
|
82
|
-
if (
|
|
82
|
+
const service = services[serviceName] && services[serviceName]
|
|
83
|
+
if (service && service.requestInject) service.requestInject(span, request, tracer)
|
|
83
84
|
},
|
|
84
85
|
|
|
85
86
|
wrapCb (cb, serviceName, tags, request, tracer, childOf) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const log = require('../../../dd-trace/src/log')
|
|
3
|
+
class EventBridge {
|
|
4
|
+
generateTags (params, operation, response) {
|
|
5
|
+
if (!params || !params.source) return {}
|
|
6
|
+
|
|
7
|
+
return {
|
|
8
|
+
'resource.name': `${operation} ${params.source}`,
|
|
9
|
+
'aws.eventbridge.source': params.source
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* requestInject
|
|
15
|
+
* @param {*} span
|
|
16
|
+
* @param {*} request
|
|
17
|
+
* @param {*} tracer
|
|
18
|
+
*
|
|
19
|
+
* Docs: https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutEventsRequestEntry.html
|
|
20
|
+
* We cannot use the traceHeader field as that's reserved for X-Ray.
|
|
21
|
+
* Detail must be a valid JSON string
|
|
22
|
+
* Max size per event is 256kb (https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-putevent-size.html)
|
|
23
|
+
*/
|
|
24
|
+
requestInject (span, request, tracer) {
|
|
25
|
+
const operation = request.operation
|
|
26
|
+
if (operation === 'putEvents' &&
|
|
27
|
+
request.params &&
|
|
28
|
+
request.params.Entries &&
|
|
29
|
+
request.params.Entries.length > 0 &&
|
|
30
|
+
request.params.Entries[0].Detail) {
|
|
31
|
+
try {
|
|
32
|
+
const details = JSON.parse(request.params.Entries[0].Detail)
|
|
33
|
+
details._datadog = {}
|
|
34
|
+
tracer.inject(span, 'text_map', details._datadog)
|
|
35
|
+
const finalData = JSON.stringify(details)
|
|
36
|
+
const byteSize = Buffer.byteLength(finalData)
|
|
37
|
+
if (byteSize >= (1024 * 256)) {
|
|
38
|
+
log.info('Payload size too large to pass context')
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
request.params.Entries[0].Detail = finalData
|
|
42
|
+
} catch (e) {
|
|
43
|
+
log.error(e)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
module.exports = EventBridge
|
|
@@ -1,15 +1,65 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
2
|
+
const log = require('../../../dd-trace/src/log')
|
|
3
3
|
class Kinesis {
|
|
4
4
|
generateTags (params, operation, response) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
if (!params || !params.StreamName) return tags
|
|
5
|
+
if (!params || !params.StreamName) return {}
|
|
8
6
|
|
|
9
|
-
return
|
|
7
|
+
return {
|
|
10
8
|
'resource.name': `${operation} ${params.StreamName}`,
|
|
11
9
|
'aws.kinesis.stream_name': params.StreamName
|
|
12
|
-
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// AWS-SDK will b64 kinesis payloads
|
|
14
|
+
// or will accept an already b64 encoded payload
|
|
15
|
+
// This method handles both
|
|
16
|
+
_tryParse (body) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(body)
|
|
19
|
+
} catch (e) {
|
|
20
|
+
log.info('Not JSON string. Trying Base64 encoded JSON string')
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
return JSON.parse(Buffer.from(body, 'base64').toString('ascii'), true)
|
|
24
|
+
} catch (e) {
|
|
25
|
+
return null
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
requestInject (span, request, tracer) {
|
|
30
|
+
const operation = request.operation
|
|
31
|
+
if (operation === 'putRecord' || operation === 'putRecords') {
|
|
32
|
+
if (!request.params) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const traceData = {}
|
|
37
|
+
tracer.inject(span, 'text_map', traceData)
|
|
38
|
+
let injectPath
|
|
39
|
+
if (request.params.Records && request.params.Records.length > 0) {
|
|
40
|
+
injectPath = request.params.Records[0]
|
|
41
|
+
} else if (request.params.Data) {
|
|
42
|
+
injectPath = request.params
|
|
43
|
+
} else {
|
|
44
|
+
log.error('No valid payload passed, unable to pass trace context')
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
const parsedData = this._tryParse(injectPath.Data)
|
|
48
|
+
if (parsedData) {
|
|
49
|
+
parsedData._datadog = traceData
|
|
50
|
+
const finalData = JSON.stringify(parsedData)
|
|
51
|
+
const byteSize = Buffer.byteLength(finalData, 'ascii')
|
|
52
|
+
// Kinesis max payload size is 1MB
|
|
53
|
+
// So we must ensure adding DD context won't go over that (512b is an estimate)
|
|
54
|
+
if (byteSize >= 1048576) {
|
|
55
|
+
log.info('Payload size too large to pass context')
|
|
56
|
+
return
|
|
57
|
+
}
|
|
58
|
+
injectPath.Data = finalData
|
|
59
|
+
} else {
|
|
60
|
+
log.error('Unable to parse payload, unable to pass trace context')
|
|
61
|
+
}
|
|
62
|
+
}
|
|
13
63
|
}
|
|
14
64
|
}
|
|
15
65
|
|
|
@@ -1,21 +1,48 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
const log = require('../../../dd-trace/src/log')
|
|
2
3
|
|
|
3
4
|
class Sns {
|
|
4
5
|
generateTags (params, operation, response) {
|
|
5
|
-
|
|
6
|
+
if (!params) return {}
|
|
6
7
|
|
|
7
|
-
if (!params) return
|
|
8
|
+
if (!params.TopicArn && !(response.data && response.data.TopicArn)) return {}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return Object.assign(tags, {
|
|
10
|
+
return {
|
|
12
11
|
'resource.name': `${operation} ${params.TopicArn || response.data.TopicArn}`,
|
|
13
12
|
'aws.sns.topic_arn': params.TopicArn || response.data.TopicArn
|
|
14
|
-
}
|
|
13
|
+
}
|
|
15
14
|
|
|
16
15
|
// TODO: should arn be sanitized or quantized in some way here,
|
|
17
16
|
// for example if it contains a phone number?
|
|
18
17
|
}
|
|
18
|
+
|
|
19
|
+
requestInject (span, request, tracer) {
|
|
20
|
+
const operation = request.operation
|
|
21
|
+
if (operation === 'publish' || operation === 'publishBatch') {
|
|
22
|
+
if (!request.params) {
|
|
23
|
+
request.params = {}
|
|
24
|
+
}
|
|
25
|
+
let injectPath
|
|
26
|
+
if (request.params.PublishBatchRequestEntries && request.params.PublishBatchRequestEntries.length > 0) {
|
|
27
|
+
injectPath = request.params.PublishBatchRequestEntries[0]
|
|
28
|
+
} else if (request.params.Message) {
|
|
29
|
+
injectPath = request.params
|
|
30
|
+
}
|
|
31
|
+
if (!injectPath.MessageAttributes) {
|
|
32
|
+
injectPath.MessageAttributes = {}
|
|
33
|
+
}
|
|
34
|
+
if (Object.keys(injectPath.MessageAttributes).length >= 10) { // SNS quota
|
|
35
|
+
log.info('Message attributes full, skipping trace context injection')
|
|
36
|
+
return
|
|
37
|
+
}
|
|
38
|
+
const ddInfo = {}
|
|
39
|
+
tracer.inject(span, 'text_map', ddInfo)
|
|
40
|
+
injectPath.MessageAttributes._datadog = {
|
|
41
|
+
DataType: 'String',
|
|
42
|
+
StringValue: JSON.stringify(ddInfo)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
19
46
|
}
|
|
20
47
|
|
|
21
48
|
module.exports = Sns
|