dd-trace 3.12.1 → 3.15.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/LICENSE-3rdparty.csv +1 -0
- package/README.md +5 -5
- package/ci/init.js +3 -1
- package/index.d.ts +100 -1
- package/package.json +5 -4
- package/packages/datadog-instrumentations/src/aws-sdk.js +86 -0
- package/packages/datadog-instrumentations/src/cucumber.js +74 -15
- package/packages/datadog-instrumentations/src/cypress.js +1 -1
- package/packages/datadog-instrumentations/src/fs.js +358 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +24 -23
- package/packages/datadog-instrumentations/src/ldapjs.js +12 -2
- package/packages/datadog-instrumentations/src/mocha.js +10 -7
- package/packages/datadog-instrumentations/src/mongoose.js +1 -1
- package/packages/datadog-instrumentations/src/mysql.js +7 -1
- package/packages/datadog-instrumentations/src/mysql2.js +7 -1
- package/packages/datadog-instrumentations/src/next.js +2 -1
- package/packages/datadog-instrumentations/src/playwright.js +263 -0
- package/packages/datadog-plugin-aws-sdk/src/base.js +12 -5
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +29 -24
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +31 -16
- package/packages/datadog-plugin-cucumber/src/index.js +42 -11
- package/packages/datadog-plugin-cypress/src/plugin.js +129 -4
- package/packages/datadog-plugin-cypress/src/support.js +5 -0
- package/packages/datadog-plugin-fs/src/index.js +45 -0
- package/packages/datadog-plugin-hapi/src/index.js +5 -1
- package/packages/datadog-plugin-http/src/server.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +40 -70
- package/packages/datadog-plugin-mocha/src/index.js +44 -64
- package/packages/datadog-plugin-mysql/src/index.js +8 -7
- package/packages/datadog-plugin-playwright/src/index.js +112 -0
- package/packages/datadog-shimmer/src/shimmer.js +28 -11
- package/packages/dd-trace/src/appsec/addresses.js +3 -1
- package/packages/dd-trace/src/appsec/blocking.js +35 -9
- package/packages/dd-trace/src/appsec/callbacks/ddwaf.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +60 -0
- package/packages/dd-trace/src/appsec/iast/iast-context.js +6 -2
- package/packages/dd-trace/src/appsec/iast/index.js +3 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +5 -2
- package/packages/dd-trace/src/appsec/index.js +5 -5
- package/packages/dd-trace/src/appsec/recommended.json +320 -184
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +3 -0
- package/packages/dd-trace/src/appsec/reporter.js +14 -14
- package/packages/dd-trace/src/appsec/sdk/index.js +41 -0
- package/packages/dd-trace/src/appsec/sdk/noop.js +17 -0
- package/packages/dd-trace/src/appsec/sdk/set_user.js +30 -0
- package/packages/dd-trace/src/appsec/sdk/track_event.js +74 -0
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +73 -0
- package/packages/dd-trace/src/appsec/sdk/utils.js +10 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +1 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -5
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +48 -11
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +7 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +4 -2
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +5 -3
- package/packages/dd-trace/src/config.js +63 -7
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/encode/0.5.js +1 -1
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +44 -4
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +52 -37
- package/packages/dd-trace/src/encode/tags-processors.js +3 -2
- package/packages/dd-trace/src/exporters/common/request.js +10 -3
- package/packages/dd-trace/src/lambda/handler.js +5 -6
- package/packages/dd-trace/src/log/channels.js +47 -0
- package/packages/dd-trace/src/log/index.js +79 -0
- package/packages/dd-trace/src/log/writer.js +124 -0
- package/packages/dd-trace/src/metrics.js +18 -0
- package/packages/dd-trace/src/noop/proxy.js +5 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +188 -36
- package/packages/dd-trace/src/opentracing/propagation/tracestate.js +99 -0
- package/packages/dd-trace/src/opentracing/span.js +2 -1
- package/packages/dd-trace/src/opentracing/span_context.js +6 -3
- package/packages/dd-trace/src/plugins/ci_plugin.js +72 -12
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/util/ci.js +13 -21
- package/packages/dd-trace/src/plugins/util/exec.js +2 -2
- package/packages/dd-trace/src/plugins/util/git.js +16 -1
- package/packages/dd-trace/src/{appsec → plugins/util}/ip_extractor.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +53 -10
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -7
- package/packages/dd-trace/src/plugins/util/web.js +11 -0
- package/packages/dd-trace/src/profiler.js +3 -0
- package/packages/dd-trace/src/profiling/config.js +8 -3
- package/packages/dd-trace/src/profiling/exporters/file.js +13 -2
- package/packages/dd-trace/src/profiling/profiler.js +23 -6
- package/packages/dd-trace/src/profiling/profilers/wall.js +1 -0
- package/packages/dd-trace/src/proxy.js +2 -0
- package/packages/dd-trace/src/span_processor.js +1 -1
- package/packages/dd-trace/src/span_sampler.js +68 -52
- package/packages/dd-trace/src/startup-log.js +3 -6
- package/packages/dd-trace/src/telemetry/index.js +23 -2
- package/packages/dd-trace/src/telemetry/send-data.js +4 -1
- package/packages/dd-trace/src/tracer.js +0 -16
- package/scripts/check-proposal-labels.js +71 -0
- package/packages/dd-trace/src/log.js +0 -143
- /package/packages/dd-trace/src/{appsec → plugins/util}/ip_blocklist.js +0 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
channel,
|
|
6
|
+
addHook,
|
|
7
|
+
AsyncResource
|
|
8
|
+
} = require('./helpers/instrument')
|
|
9
|
+
const shimmer = require('../../datadog-shimmer')
|
|
10
|
+
|
|
11
|
+
const startChannel = channel('apm:fs:operation:start')
|
|
12
|
+
const finishChannel = channel('apm:fs:operation:finish')
|
|
13
|
+
const errorChannel = channel('apm:fs:operation:error')
|
|
14
|
+
const ddFhSym = Symbol('ddFileHandle')
|
|
15
|
+
let kHandle, kDirReadPromisified, kDirClosePromisified
|
|
16
|
+
|
|
17
|
+
const paramsByMethod = {
|
|
18
|
+
access: ['path', 'mode'],
|
|
19
|
+
appendFile: ['path', 'data', 'options'],
|
|
20
|
+
chmod: ['path', 'mode'],
|
|
21
|
+
chown: ['path', 'uid', 'gid'],
|
|
22
|
+
close: ['fd'],
|
|
23
|
+
copyFile: ['src', 'dest', 'mode'],
|
|
24
|
+
cp: ['src', 'dest', 'options'],
|
|
25
|
+
exists: ['path'],
|
|
26
|
+
fchmod: ['fd', 'mode'],
|
|
27
|
+
fchown: ['fd', 'uid', 'gid'],
|
|
28
|
+
fdatasync: ['fd'],
|
|
29
|
+
fstat: ['fd', 'options'],
|
|
30
|
+
fsync: ['fd'],
|
|
31
|
+
ftruncate: ['fd', 'len'],
|
|
32
|
+
futimes: ['fd', 'atime', 'mtime'],
|
|
33
|
+
lchmod: ['path', 'mode'],
|
|
34
|
+
lchown: ['path', 'uid', 'gid'],
|
|
35
|
+
link: ['existingPath', 'newPath'],
|
|
36
|
+
lstat: ['path', 'options'],
|
|
37
|
+
lutimes: ['path', 'atime', 'mtime'],
|
|
38
|
+
mkdir: ['path', 'options'],
|
|
39
|
+
mkdtemp: ['prefix', 'options'],
|
|
40
|
+
open: ['path', 'flag', 'mode'],
|
|
41
|
+
opendir: ['path', 'options'],
|
|
42
|
+
read: ['fd'],
|
|
43
|
+
readdir: ['path', 'options'],
|
|
44
|
+
readFile: ['path', 'options'],
|
|
45
|
+
readlink: ['path', 'options'],
|
|
46
|
+
readv: ['fd'],
|
|
47
|
+
realpath: ['path', 'options'],
|
|
48
|
+
rename: ['oldPath', 'newPath'],
|
|
49
|
+
rmdir: ['path', 'options'],
|
|
50
|
+
rm: ['path', 'options'],
|
|
51
|
+
stat: ['path', 'options'],
|
|
52
|
+
symlink: ['target', 'path', 'type'],
|
|
53
|
+
truncate: ['path', 'len'],
|
|
54
|
+
unlink: ['path'],
|
|
55
|
+
utimes: ['path', 'atime', 'mtime'],
|
|
56
|
+
write: ['fd'],
|
|
57
|
+
writeFile: ['file', 'data', 'options'],
|
|
58
|
+
writev: ['fd']
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const watchMethods = {
|
|
62
|
+
unwatchFile: ['path', 'listener'],
|
|
63
|
+
watch: ['path', 'options', 'listener'],
|
|
64
|
+
watchFile: ['path', 'options', 'listener']
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const paramsByFileHandleMethods = {
|
|
68
|
+
appendFile: ['data', 'options'],
|
|
69
|
+
chmod: ['mode'],
|
|
70
|
+
chown: ['uid', 'gid'],
|
|
71
|
+
close: [],
|
|
72
|
+
createReadStream: ['options'],
|
|
73
|
+
createWriteStream: ['options'],
|
|
74
|
+
datasync: [],
|
|
75
|
+
read: ['buffer', 'offset', 'length', 'position'],
|
|
76
|
+
readableWebStream: [],
|
|
77
|
+
readFile: ['options'],
|
|
78
|
+
readLines: ['options'],
|
|
79
|
+
readv: ['buffers', 'position'],
|
|
80
|
+
stat: ['options'],
|
|
81
|
+
sync: [],
|
|
82
|
+
truncate: ['len'],
|
|
83
|
+
utimes: ['atime', 'mtime'],
|
|
84
|
+
write: ['buffer', 'offset', 'length', 'position'],
|
|
85
|
+
writeFile: ['data', 'options'],
|
|
86
|
+
writev: ['buffers', 'position']
|
|
87
|
+
}
|
|
88
|
+
const names = ['fs', 'node:fs']
|
|
89
|
+
names.forEach(name => {
|
|
90
|
+
addHook({ name }, fs => {
|
|
91
|
+
const asyncMethods = Object.keys(paramsByMethod)
|
|
92
|
+
const syncMethods = asyncMethods.map(name => `${name}Sync`)
|
|
93
|
+
|
|
94
|
+
massWrap(fs, asyncMethods, createWrapFunction())
|
|
95
|
+
massWrap(fs, syncMethods, createWrapFunction())
|
|
96
|
+
massWrap(fs.promises, asyncMethods, createWrapFunction('promises.'))
|
|
97
|
+
|
|
98
|
+
wrap(fs.realpath, 'native', createWrapFunction('', 'realpath.native'))
|
|
99
|
+
wrap(fs.realpathSync, 'native', createWrapFunction('', 'realpath.native'))
|
|
100
|
+
wrap(fs.promises.realpath, 'native', createWrapFunction('', 'realpath.native'))
|
|
101
|
+
|
|
102
|
+
wrap(fs, 'createReadStream', wrapCreateStream)
|
|
103
|
+
wrap(fs, 'createWriteStream', wrapCreateStream)
|
|
104
|
+
if (fs.Dir) {
|
|
105
|
+
wrap(fs.Dir.prototype, 'close', createWrapFunction('dir.'))
|
|
106
|
+
wrap(fs.Dir.prototype, 'closeSync', createWrapFunction('dir.'))
|
|
107
|
+
wrap(fs.Dir.prototype, 'read', createWrapFunction('dir.'))
|
|
108
|
+
wrap(fs.Dir.prototype, 'readSync', createWrapFunction('dir.'))
|
|
109
|
+
wrap(fs.Dir.prototype, Symbol.asyncIterator, createWrapDirAsyncIterator())
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
wrap(fs, 'unwatchFile', createWatchWrapFunction())
|
|
113
|
+
wrap(fs, 'watch', createWatchWrapFunction())
|
|
114
|
+
wrap(fs, 'watchFile', createWatchWrapFunction())
|
|
115
|
+
|
|
116
|
+
return fs
|
|
117
|
+
})
|
|
118
|
+
})
|
|
119
|
+
function isFirstMethodReturningFileHandle (original) {
|
|
120
|
+
return !kHandle && original.name === 'open'
|
|
121
|
+
}
|
|
122
|
+
function wrapFileHandle (fh) {
|
|
123
|
+
const fileHandlePrototype = getFileHandlePrototype(fh)
|
|
124
|
+
const desc = Reflect.getOwnPropertyDescriptor(fileHandlePrototype, kHandle)
|
|
125
|
+
if (!desc || !desc.get) {
|
|
126
|
+
Reflect.defineProperty(fileHandlePrototype, kHandle, {
|
|
127
|
+
get () {
|
|
128
|
+
return this[ddFhSym]
|
|
129
|
+
},
|
|
130
|
+
set (h) {
|
|
131
|
+
this[ddFhSym] = h
|
|
132
|
+
wrap(this, 'close', createWrapFunction('filehandle.'))
|
|
133
|
+
},
|
|
134
|
+
configurable: true
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
for (const name of Reflect.ownKeys(fileHandlePrototype)) {
|
|
138
|
+
if (typeof name !== 'string' || name === 'constructor' || name === 'fd' || name === 'getAsyncId') {
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
wrap(fileHandlePrototype, name, createWrapFunction('filehandle.'))
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function getFileHandlePrototype (fh) {
|
|
146
|
+
if (!kHandle) {
|
|
147
|
+
kHandle = Reflect.ownKeys(fh).find(key => typeof key === 'symbol' && key.toString().includes('kHandle'))
|
|
148
|
+
}
|
|
149
|
+
return Object.getPrototypeOf(fh)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function getSymbolName (sym) {
|
|
153
|
+
return sym.description || sym.toString()
|
|
154
|
+
}
|
|
155
|
+
function initDirAsyncIteratorProperties (iterator) {
|
|
156
|
+
const keys = Reflect.ownKeys(iterator)
|
|
157
|
+
for (const key of keys) {
|
|
158
|
+
if (kDirReadPromisified && kDirClosePromisified) break
|
|
159
|
+
if (typeof key !== 'symbol') continue
|
|
160
|
+
if (!kDirReadPromisified && getSymbolName(key).includes('kDirReadPromisified')) {
|
|
161
|
+
kDirReadPromisified = key
|
|
162
|
+
}
|
|
163
|
+
if (!kDirClosePromisified && getSymbolName(key).includes('kDirClosePromisified')) {
|
|
164
|
+
kDirClosePromisified = key
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function createWrapDirAsyncIterator () {
|
|
170
|
+
return function wrapDirAsyncIterator (asyncIterator) {
|
|
171
|
+
return function wrappedAsyncIterator () {
|
|
172
|
+
if (!kDirReadPromisified || !kDirClosePromisified) {
|
|
173
|
+
initDirAsyncIteratorProperties(this)
|
|
174
|
+
}
|
|
175
|
+
wrap(this, kDirReadPromisified, createWrapFunction('dir.', 'read'))
|
|
176
|
+
wrap(this, kDirClosePromisified, createWrapFunction('dir.', 'close'))
|
|
177
|
+
return asyncIterator.apply(this, arguments)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function wrapCreateStream (original) {
|
|
183
|
+
const classes = {
|
|
184
|
+
createReadStream: 'ReadStream',
|
|
185
|
+
createWriteStream: 'WriteStream'
|
|
186
|
+
}
|
|
187
|
+
const name = classes[original.name]
|
|
188
|
+
|
|
189
|
+
return function (path, options) {
|
|
190
|
+
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
191
|
+
|
|
192
|
+
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
193
|
+
const message = getMessage(name, ['path', 'options'], arguments)
|
|
194
|
+
|
|
195
|
+
return innerResource.runInAsyncScope(() => {
|
|
196
|
+
startChannel.publish(message)
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const stream = original.apply(this, arguments)
|
|
200
|
+
const onError = innerResource.bind(error => {
|
|
201
|
+
errorChannel.publish(error)
|
|
202
|
+
onFinish()
|
|
203
|
+
})
|
|
204
|
+
const onFinish = innerResource.bind(() => {
|
|
205
|
+
finishChannel.publish()
|
|
206
|
+
stream.off('close', onFinish)
|
|
207
|
+
stream.off('end', onFinish)
|
|
208
|
+
stream.off('finish', onFinish)
|
|
209
|
+
stream.off('error', onError)
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
stream.once('close', onFinish)
|
|
213
|
+
stream.once('end', onFinish)
|
|
214
|
+
stream.once('finish', onFinish)
|
|
215
|
+
stream.once('error', onError)
|
|
216
|
+
|
|
217
|
+
return stream
|
|
218
|
+
} catch (error) {
|
|
219
|
+
errorChannel.publish(error)
|
|
220
|
+
finishChannel.publish()
|
|
221
|
+
}
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function getMethodParamsRelationByPrefix (prefix) {
|
|
227
|
+
if (prefix === 'filehandle.') {
|
|
228
|
+
return paramsByFileHandleMethods
|
|
229
|
+
}
|
|
230
|
+
return paramsByMethod
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function createWatchWrapFunction (override = '') {
|
|
234
|
+
return function wrapFunction (original) {
|
|
235
|
+
const name = override || original.name
|
|
236
|
+
const method = name
|
|
237
|
+
const operation = name
|
|
238
|
+
return function () {
|
|
239
|
+
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
240
|
+
const message = getMessage(method, watchMethods[operation], arguments, this)
|
|
241
|
+
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
242
|
+
return innerResource.runInAsyncScope(() => {
|
|
243
|
+
startChannel.publish(message)
|
|
244
|
+
try {
|
|
245
|
+
const result = original.apply(this, arguments)
|
|
246
|
+
finishChannel.publish()
|
|
247
|
+
return result
|
|
248
|
+
} catch (error) {
|
|
249
|
+
errorChannel.publish(error)
|
|
250
|
+
finishChannel.publish()
|
|
251
|
+
throw error
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function createWrapFunction (prefix = '', override = '') {
|
|
259
|
+
return function wrapFunction (original) {
|
|
260
|
+
const name = override || original.name
|
|
261
|
+
const method = `${prefix}${name}`
|
|
262
|
+
const operation = name.match(/^(.+?)(Sync)?(\.native)?$/)[1]
|
|
263
|
+
|
|
264
|
+
return function () {
|
|
265
|
+
if (!startChannel.hasSubscribers) return original.apply(this, arguments)
|
|
266
|
+
|
|
267
|
+
const lastIndex = arguments.length - 1
|
|
268
|
+
const cb = typeof arguments[lastIndex] === 'function' && arguments[lastIndex]
|
|
269
|
+
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
270
|
+
const message = getMessage(method, getMethodParamsRelationByPrefix(prefix)[operation], arguments, this)
|
|
271
|
+
|
|
272
|
+
if (cb) {
|
|
273
|
+
const outerResource = new AsyncResource('bound-anonymous-fn')
|
|
274
|
+
|
|
275
|
+
arguments[lastIndex] = innerResource.bind(function (e) {
|
|
276
|
+
if (typeof e === 'object') { // fs.exists receives a boolean
|
|
277
|
+
errorChannel.publish(e)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
finishChannel.publish()
|
|
281
|
+
|
|
282
|
+
return outerResource.runInAsyncScope(() => cb.apply(this, arguments))
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return innerResource.runInAsyncScope(() => {
|
|
287
|
+
startChannel.publish(message)
|
|
288
|
+
try {
|
|
289
|
+
const result = original.apply(this, arguments)
|
|
290
|
+
if (cb) return result
|
|
291
|
+
if (result && typeof result.then === 'function') {
|
|
292
|
+
// TODO method open returning promise and filehandle prototype not initialized, initialize it
|
|
293
|
+
|
|
294
|
+
return result.then(
|
|
295
|
+
value => {
|
|
296
|
+
if (isFirstMethodReturningFileHandle(original)) {
|
|
297
|
+
wrapFileHandle(value)
|
|
298
|
+
}
|
|
299
|
+
finishChannel.publish()
|
|
300
|
+
return value
|
|
301
|
+
},
|
|
302
|
+
error => {
|
|
303
|
+
errorChannel.publish(error)
|
|
304
|
+
finishChannel.publish()
|
|
305
|
+
throw error
|
|
306
|
+
}
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
finishChannel.publish()
|
|
311
|
+
|
|
312
|
+
return result
|
|
313
|
+
} catch (error) {
|
|
314
|
+
errorChannel.publish(error)
|
|
315
|
+
finishChannel.publish()
|
|
316
|
+
throw error
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function getMessage (operation, params, args, self) {
|
|
324
|
+
const metadata = {}
|
|
325
|
+
if (params) {
|
|
326
|
+
for (let i = 0; i < params.length; i++) {
|
|
327
|
+
if (!params[i] || typeof args[i] === 'function') continue
|
|
328
|
+
metadata[params[i]] = args[i]
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (self) {
|
|
333
|
+
// For `Dir` the path is available on `this.path`
|
|
334
|
+
if (self.path) {
|
|
335
|
+
metadata.path = self.path
|
|
336
|
+
}
|
|
337
|
+
// For FileHandle fs is available on `this.fd`
|
|
338
|
+
if (self.fd) {
|
|
339
|
+
metadata.fd = self.fd
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return { operation, ...metadata }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function massWrap (target, methods, wrapper) {
|
|
347
|
+
for (const method of methods) {
|
|
348
|
+
wrap(target, method, wrapper)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function wrap (target, method, wrapper) {
|
|
353
|
+
try {
|
|
354
|
+
shimmer.wrap(target, method, wrapper)
|
|
355
|
+
} catch (e) {
|
|
356
|
+
// skip unavailable method
|
|
357
|
+
}
|
|
358
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
module.exports = {
|
|
4
|
+
'@aws-sdk/smithy-client': () => require('../aws-sdk'),
|
|
4
5
|
'@cucumber/cucumber': () => require('../cucumber'),
|
|
6
|
+
'@playwright/test': () => require('../playwright'),
|
|
5
7
|
'@elastic/elasticsearch': () => require('../elasticsearch'),
|
|
6
8
|
'@elastic/transport': () => require('../elasticsearch'),
|
|
7
9
|
'@google-cloud/pubsub': () => require('../google-cloud-pubsub'),
|
|
@@ -31,6 +33,8 @@ module.exports = {
|
|
|
31
33
|
'express': () => require('../express'),
|
|
32
34
|
'fastify': () => require('../fastify'),
|
|
33
35
|
'find-my-way': () => require('../find-my-way'),
|
|
36
|
+
'fs': () => require('../fs'),
|
|
37
|
+
'node:fs': () => require('../fs'),
|
|
34
38
|
'graphql': () => require('../graphql'),
|
|
35
39
|
'grpc': () => require('../grpc'),
|
|
36
40
|
'hapi': () => require('../hapi'),
|
|
@@ -72,7 +72,7 @@ function getTestEnvironmentOptions (config) {
|
|
|
72
72
|
return {}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function getWrappedEnvironment (BaseEnvironment) {
|
|
75
|
+
function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
76
76
|
return class DatadogEnvironment extends BaseEnvironment {
|
|
77
77
|
constructor (config, context) {
|
|
78
78
|
super(config, context)
|
|
@@ -116,7 +116,8 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
116
116
|
name: getJestTestName(event.test),
|
|
117
117
|
suite: this.testSuite,
|
|
118
118
|
runner: 'jest-circus',
|
|
119
|
-
testParameters
|
|
119
|
+
testParameters,
|
|
120
|
+
frameworkVersion: jestVersion
|
|
120
121
|
})
|
|
121
122
|
originalTestFns.set(event.test, event.test.fn)
|
|
122
123
|
event.test.fn = asyncResource.bind(event.test.fn)
|
|
@@ -142,7 +143,8 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
142
143
|
testSkippedCh.publish({
|
|
143
144
|
name: getJestTestName(event.test),
|
|
144
145
|
suite: this.testSuite,
|
|
145
|
-
runner: 'jest-circus'
|
|
146
|
+
runner: 'jest-circus',
|
|
147
|
+
frameworkVersion: jestVersion
|
|
146
148
|
})
|
|
147
149
|
})
|
|
148
150
|
}
|
|
@@ -150,14 +152,14 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
function getTestEnvironment (pkg) {
|
|
155
|
+
function getTestEnvironment (pkg, jestVersion) {
|
|
154
156
|
if (pkg.default) {
|
|
155
|
-
const wrappedTestEnvironment = getWrappedEnvironment(pkg.default)
|
|
157
|
+
const wrappedTestEnvironment = getWrappedEnvironment(pkg.default, jestVersion)
|
|
156
158
|
pkg.default = wrappedTestEnvironment
|
|
157
159
|
pkg.TestEnvironment = wrappedTestEnvironment
|
|
158
160
|
return pkg
|
|
159
161
|
}
|
|
160
|
-
return getWrappedEnvironment(pkg)
|
|
162
|
+
return getWrappedEnvironment(pkg, jestVersion)
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
addHook({
|
|
@@ -170,7 +172,7 @@ addHook({
|
|
|
170
172
|
versions: ['>=24.8.0']
|
|
171
173
|
}, getTestEnvironment)
|
|
172
174
|
|
|
173
|
-
function cliWrapper (cli) {
|
|
175
|
+
function cliWrapper (cli, jestVersion) {
|
|
174
176
|
const wrapped = shimmer.wrap(cli, 'runCLI', runCLI => async function () {
|
|
175
177
|
let onDone
|
|
176
178
|
const configurationPromise = new Promise((resolve) => {
|
|
@@ -186,13 +188,12 @@ function cliWrapper (cli) {
|
|
|
186
188
|
|
|
187
189
|
try {
|
|
188
190
|
const { err, itrConfig } = await configurationPromise
|
|
189
|
-
if (err) {
|
|
190
|
-
|
|
191
|
+
if (!err) {
|
|
192
|
+
isCodeCoverageEnabled = itrConfig.isCodeCoverageEnabled
|
|
193
|
+
isSuitesSkippingEnabled = itrConfig.isSuitesSkippingEnabled
|
|
191
194
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
} catch (e) {
|
|
195
|
-
log.error(e)
|
|
195
|
+
} catch (err) {
|
|
196
|
+
log.error(err)
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
if (isSuitesSkippingEnabled) {
|
|
@@ -206,13 +207,11 @@ function cliWrapper (cli) {
|
|
|
206
207
|
|
|
207
208
|
try {
|
|
208
209
|
const { err, skippableSuites: receivedSkippableSuites } = await skippableSuitesPromise
|
|
209
|
-
if (err) {
|
|
210
|
-
log.error(err)
|
|
211
|
-
} else {
|
|
210
|
+
if (!err) {
|
|
212
211
|
skippableSuites = receivedSkippableSuites
|
|
213
212
|
}
|
|
214
|
-
} catch (
|
|
215
|
-
log.error(
|
|
213
|
+
} catch (err) {
|
|
214
|
+
log.error(err)
|
|
216
215
|
}
|
|
217
216
|
}
|
|
218
217
|
|
|
@@ -220,7 +219,7 @@ function cliWrapper (cli) {
|
|
|
220
219
|
|
|
221
220
|
const processArgv = process.argv.slice(2).join(' ')
|
|
222
221
|
sessionAsyncResource.runInAsyncScope(() => {
|
|
223
|
-
testSessionStartCh.publish(`jest ${processArgv}
|
|
222
|
+
testSessionStartCh.publish({ command: `jest ${processArgv}`, frameworkVersion: jestVersion })
|
|
224
223
|
})
|
|
225
224
|
|
|
226
225
|
const result = await runCLI.apply(this, arguments)
|
|
@@ -288,7 +287,7 @@ addHook({
|
|
|
288
287
|
versions: ['>=24.8.0']
|
|
289
288
|
}, cliWrapper)
|
|
290
289
|
|
|
291
|
-
function jestAdapterWrapper (jestAdapter) {
|
|
290
|
+
function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
292
291
|
const adapter = jestAdapter.default ? jestAdapter.default : jestAdapter
|
|
293
292
|
const newAdapter = shimmer.wrap(adapter, function () {
|
|
294
293
|
const environment = arguments[2]
|
|
@@ -299,7 +298,8 @@ function jestAdapterWrapper (jestAdapter) {
|
|
|
299
298
|
return asyncResource.runInAsyncScope(() => {
|
|
300
299
|
testSuiteStartCh.publish({
|
|
301
300
|
testSuite: environment.testSuite,
|
|
302
|
-
testEnvironmentOptions: environment.testEnvironmentOptions
|
|
301
|
+
testEnvironmentOptions: environment.testEnvironmentOptions,
|
|
302
|
+
frameworkVersion: jestVersion
|
|
303
303
|
})
|
|
304
304
|
return adapter.apply(this, arguments).then(suiteResults => {
|
|
305
305
|
const { numFailingTests, skipped, failureMessage: errorMessage } = suiteResults
|
|
@@ -440,7 +440,7 @@ addHook({
|
|
|
440
440
|
versions: ['24.8.0 - 24.9.0']
|
|
441
441
|
}, jestConfigSyncWrapper)
|
|
442
442
|
|
|
443
|
-
function jasmineAsyncInstallWraper (jasmineAsyncInstallExport) {
|
|
443
|
+
function jasmineAsyncInstallWraper (jasmineAsyncInstallExport, jestVersion) {
|
|
444
444
|
return function (globalConfig, globalInput) {
|
|
445
445
|
globalInput._ddtrace = global._ddtrace
|
|
446
446
|
shimmer.wrap(globalInput.jasmine.Spec.prototype, 'execute', execute => function (onComplete) {
|
|
@@ -450,7 +450,8 @@ function jasmineAsyncInstallWraper (jasmineAsyncInstallExport) {
|
|
|
450
450
|
testStartCh.publish({
|
|
451
451
|
name: this.getFullName(),
|
|
452
452
|
suite: testSuite,
|
|
453
|
-
runner: 'jest-jasmine2'
|
|
453
|
+
runner: 'jest-jasmine2',
|
|
454
|
+
frameworkVersion: jestVersion
|
|
454
455
|
})
|
|
455
456
|
const spec = this
|
|
456
457
|
const callback = asyncResource.bind(function () {
|
|
@@ -35,7 +35,7 @@ function wrapEmitter (corkedEmitter) {
|
|
|
35
35
|
}
|
|
36
36
|
arguments[1] = bindedFn
|
|
37
37
|
}
|
|
38
|
-
on.apply(this, arguments)
|
|
38
|
+
return on.apply(this, arguments)
|
|
39
39
|
}
|
|
40
40
|
shimmer.wrap(corkedEmitter, 'on', addListener)
|
|
41
41
|
shimmer.wrap(corkedEmitter, 'addListener', addListener)
|
|
@@ -47,7 +47,7 @@ function wrapEmitter (corkedEmitter) {
|
|
|
47
47
|
arguments[1] = emitterOn
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
off.apply(this, arguments)
|
|
50
|
+
return off.apply(this, arguments)
|
|
51
51
|
}
|
|
52
52
|
shimmer.wrap(corkedEmitter, 'off', removeListener)
|
|
53
53
|
shimmer.wrap(corkedEmitter, 'removeListener', removeListener)
|
|
@@ -87,5 +87,15 @@ addHook({ name: 'ldapjs', versions: ['>=2'] }, ldapjs => {
|
|
|
87
87
|
return _send.apply(this, arguments)
|
|
88
88
|
})
|
|
89
89
|
|
|
90
|
+
shimmer.wrap(ldapjs.Client.prototype, 'bind', bind => function (dn, password, controls, callback) {
|
|
91
|
+
if (typeof controls === 'function') {
|
|
92
|
+
arguments[2] = AsyncResource.bind(controls)
|
|
93
|
+
} else if (typeof callback === 'function') {
|
|
94
|
+
arguments[3] = AsyncResource.bind(callback)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return bind.apply(this, arguments)
|
|
98
|
+
})
|
|
99
|
+
|
|
90
100
|
return ldapjs
|
|
91
101
|
})
|
|
@@ -2,7 +2,6 @@ const { createCoverageMap } = require('istanbul-lib-coverage')
|
|
|
2
2
|
|
|
3
3
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
|
-
const log = require('../../dd-trace/src/log')
|
|
6
5
|
const {
|
|
7
6
|
getCoveredFilenamesFromCoverage,
|
|
8
7
|
resetCoverage,
|
|
@@ -39,6 +38,7 @@ const testFileToSuiteAr = new Map()
|
|
|
39
38
|
const originalCoverageMap = createCoverageMap()
|
|
40
39
|
|
|
41
40
|
let suitesToSkip = []
|
|
41
|
+
let frameworkVersion
|
|
42
42
|
|
|
43
43
|
function getSuitesByTestFile (root) {
|
|
44
44
|
const suitesByTestFile = {}
|
|
@@ -128,7 +128,7 @@ function mochaHook (Runner) {
|
|
|
128
128
|
this.once('start', testRunAsyncResource.bind(function () {
|
|
129
129
|
const processArgv = process.argv.slice(2).join(' ')
|
|
130
130
|
const command = `mocha ${processArgv}`
|
|
131
|
-
testSessionStartCh.publish(command)
|
|
131
|
+
testSessionStartCh.publish({ command, frameworkVersion })
|
|
132
132
|
}))
|
|
133
133
|
|
|
134
134
|
this.on('suite', function (suite) {
|
|
@@ -313,9 +313,9 @@ addHook({
|
|
|
313
313
|
name: 'mocha',
|
|
314
314
|
versions: ['>=5.2.0'],
|
|
315
315
|
file: 'lib/mocha.js'
|
|
316
|
-
}, (Mocha) => {
|
|
316
|
+
}, (Mocha, mochaVersion) => {
|
|
317
|
+
frameworkVersion = mochaVersion
|
|
317
318
|
const mochaRunAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
318
|
-
|
|
319
319
|
/**
|
|
320
320
|
* Get ITR configuration and skippable suites
|
|
321
321
|
* If ITR is disabled, `onDone` is called immediately on the subscriber
|
|
@@ -330,7 +330,6 @@ addHook({
|
|
|
330
330
|
|
|
331
331
|
const onReceivedSkippableSuites = ({ err, skippableSuites }) => {
|
|
332
332
|
if (err) {
|
|
333
|
-
log.error(err)
|
|
334
333
|
suitesToSkip = []
|
|
335
334
|
} else {
|
|
336
335
|
suitesToSkip = skippableSuites
|
|
@@ -342,7 +341,6 @@ addHook({
|
|
|
342
341
|
|
|
343
342
|
const onReceivedConfiguration = ({ err }) => {
|
|
344
343
|
if (err) {
|
|
345
|
-
log.error(err)
|
|
346
344
|
return global.run()
|
|
347
345
|
}
|
|
348
346
|
if (!skippableSuitesCh.hasSubscribers) {
|
|
@@ -417,8 +415,13 @@ addHook({
|
|
|
417
415
|
|
|
418
416
|
// we store the original function, not to lose it
|
|
419
417
|
originalFns.set(newFn, this.fn)
|
|
420
|
-
|
|
421
418
|
this.fn = newFn
|
|
419
|
+
|
|
420
|
+
// Temporarily keep functionality when .asyncResource is removed from node
|
|
421
|
+
// in https://github.com/nodejs/node/pull/46432
|
|
422
|
+
if (!this.fn.asyncResource) {
|
|
423
|
+
this.fn.asyncResource = asyncResource
|
|
424
|
+
}
|
|
422
425
|
}
|
|
423
426
|
}
|
|
424
427
|
|
|
@@ -19,7 +19,7 @@ function wrapAddQueue (addQueue) {
|
|
|
19
19
|
|
|
20
20
|
addHook({
|
|
21
21
|
name: 'mongoose',
|
|
22
|
-
versions: ['>=4.6.4']
|
|
22
|
+
versions: ['>=4.6.4 <7'] // TODO: Mongoose v7 compat
|
|
23
23
|
}, mongoose => {
|
|
24
24
|
if (mongoose.Promise !== global.Promise) {
|
|
25
25
|
shimmer.wrap(mongoose.Promise.prototype, 'then', wrapThen)
|
|
@@ -19,13 +19,19 @@ addHook({ name: 'mysql', file: 'lib/Connection.js', versions: ['>=2'] }, Connect
|
|
|
19
19
|
|
|
20
20
|
const sql = arguments[0].sql ? arguments[0].sql : arguments[0]
|
|
21
21
|
const conf = this.config
|
|
22
|
+
const payload = { sql, conf }
|
|
22
23
|
|
|
23
24
|
const callbackResource = new AsyncResource('bound-anonymous-fn')
|
|
24
25
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
25
26
|
|
|
26
27
|
return asyncResource.runInAsyncScope(() => {
|
|
27
|
-
startCh.publish(
|
|
28
|
+
startCh.publish(payload)
|
|
28
29
|
|
|
30
|
+
if (arguments[0].sql) {
|
|
31
|
+
arguments[0].sql = payload.sql
|
|
32
|
+
} else {
|
|
33
|
+
arguments[0] = payload.sql
|
|
34
|
+
}
|
|
29
35
|
try {
|
|
30
36
|
const res = query.apply(this, arguments)
|
|
31
37
|
|
|
@@ -45,8 +45,14 @@ addHook({ name: 'mysql2', file: 'lib/connection.js', versions: ['>=1'] }, Connec
|
|
|
45
45
|
|
|
46
46
|
return asyncResource.bind(function executeWithTrace (packet, connection) {
|
|
47
47
|
const sql = cmd.statement ? cmd.statement.query : cmd.sql
|
|
48
|
+
const payload = { sql, conf: config }
|
|
49
|
+
startCh.publish(payload)
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
if (cmd.statement) {
|
|
52
|
+
cmd.statement.query = payload.sql
|
|
53
|
+
} else {
|
|
54
|
+
cmd.sql = payload.sql
|
|
55
|
+
}
|
|
50
56
|
|
|
51
57
|
if (this.onResult) {
|
|
52
58
|
const onResult = callbackResource.bind(this.onResult)
|
|
@@ -127,7 +127,8 @@ function finish (req, res, result, err) {
|
|
|
127
127
|
return result
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
// TODO: 13.2 support
|
|
131
|
+
addHook({ name: 'next', versions: ['>=11.1 <13.2'], file: 'dist/server/next-server.js' }, nextServer => {
|
|
131
132
|
const Server = nextServer.default
|
|
132
133
|
|
|
133
134
|
shimmer.wrap(Server.prototype, 'handleRequest', wrapHandleRequest)
|