dd-trace 4.48.0 → 4.50.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 +3 -0
- package/index.d.ts +345 -8
- package/init.js +60 -47
- package/package.json +16 -7
- package/packages/datadog-code-origin/index.js +4 -4
- package/packages/datadog-core/index.js +1 -3
- package/packages/datadog-core/src/storage.js +21 -0
- package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-instrumentations/src/amqplib.js +65 -5
- package/packages/datadog-instrumentations/src/child_process.js +135 -27
- package/packages/datadog-instrumentations/src/express.js +1 -1
- package/packages/datadog-instrumentations/src/handlebars.js +40 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +5 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +9 -0
- package/packages/datadog-instrumentations/src/jest.js +6 -2
- package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
- package/packages/datadog-instrumentations/src/multer.js +37 -0
- package/packages/datadog-instrumentations/src/openai.js +2 -2
- package/packages/datadog-instrumentations/src/pug.js +23 -0
- package/packages/datadog-instrumentations/src/router.js +2 -3
- package/packages/datadog-instrumentations/src/url.js +84 -0
- package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
- package/packages/datadog-plugin-amqplib/src/consumer.js +6 -5
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +10 -7
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +35 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +11 -9
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +59 -45
- package/packages/datadog-plugin-cypress/src/support.js +1 -0
- package/packages/datadog-plugin-fastify/src/code_origin.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +10 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
- package/packages/datadog-plugin-grpc/src/client.js +3 -0
- package/packages/datadog-plugin-grpc/src/server.js +5 -1
- package/packages/datadog-plugin-http/src/client.js +42 -1
- package/packages/datadog-plugin-http2/src/client.js +26 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +10 -5
- package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-moleculer/src/server.js +2 -2
- package/packages/datadog-plugin-openai/src/index.js +9 -1015
- package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
- package/packages/datadog-plugin-rhea/src/consumer.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +2 -1
- package/packages/dd-trace/src/appsec/addresses.js +2 -0
- package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
- package/packages/dd-trace/src/appsec/channels.js +3 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +33 -16
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +18 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +55 -7
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +4 -2
- package/packages/dd-trace/src/appsec/index.js +9 -6
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
- package/packages/dd-trace/src/appsec/rasp/index.js +3 -0
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
- package/packages/dd-trace/src/appsec/rasp/utils.js +3 -2
- package/packages/dd-trace/src/appsec/recommended.json +354 -158
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +2 -7
- package/packages/dd-trace/src/appsec/reporter.js +6 -4
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
- package/packages/dd-trace/src/azure_metadata.js +120 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
- package/packages/dd-trace/src/config.js +88 -10
- package/packages/dd-trace/src/constants.js +8 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +98 -0
- package/packages/dd-trace/src/crashtracking/index.js +15 -0
- package/packages/dd-trace/src/crashtracking/noop.js +8 -0
- package/packages/dd-trace/src/datastreams/pathway.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +9 -13
- package/packages/dd-trace/src/debugger/devtools_client/send.js +15 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +57 -23
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +12 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +31 -20
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +11 -2
- package/packages/dd-trace/src/debugger/index.js +10 -3
- package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
- package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
- package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
- package/packages/dd-trace/src/llmobs/index.js +103 -0
- package/packages/dd-trace/src/llmobs/noop.js +82 -0
- package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
- package/packages/dd-trace/src/llmobs/sdk.js +377 -0
- package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
- package/packages/dd-trace/src/llmobs/storage.js +7 -0
- package/packages/dd-trace/src/llmobs/tagger.js +322 -0
- package/packages/dd-trace/src/llmobs/util.js +176 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
- package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +52 -0
- package/packages/dd-trace/src/log/index.js +10 -13
- package/packages/dd-trace/src/log/log.js +52 -0
- package/packages/dd-trace/src/log/writer.js +50 -19
- package/packages/dd-trace/src/noop/proxy.js +3 -0
- package/packages/dd-trace/src/noop/span.js +4 -0
- package/packages/dd-trace/src/opentelemetry/span.js +16 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +106 -32
- package/packages/dd-trace/src/opentracing/span.js +26 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/opentracing/tracer.js +8 -1
- package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
- package/packages/dd-trace/src/plugins/outbound.js +9 -0
- package/packages/dd-trace/src/plugins/tracing.js +3 -3
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +121 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +0 -1
- package/packages/dd-trace/src/plugins/util/web.js +39 -11
- package/packages/dd-trace/src/priority_sampler.js +16 -0
- package/packages/dd-trace/src/profiling/config.js +3 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -1
- package/packages/dd-trace/src/proxy.js +13 -1
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/telemetry/index.js +11 -1
- package/packages/dd-trace/src/telemetry/logs/index.js +16 -11
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -8
- package/packages/dd-trace/src/telemetry/metrics.js +6 -1
- package/packages/dd-trace/src/util.js +16 -1
- package/version.js +4 -2
- /package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/{code-injection-sensitive-analyzer.js → tainted-range-based-sensitive-analyzer.js} +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const digitRegex = /^\d+$/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Converts a flat object of tags into a nested object. For example:
|
|
7
|
+
* { 'a.b.c': 'value' } -> { a: { b: { c: 'value' } } }
|
|
8
|
+
* Also supports array-keys. For example:
|
|
9
|
+
* { 'a.0.b': 'value' } -> { a: [{ b: 'value' }] }
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} tags - Key/value pairs of tags
|
|
12
|
+
* @returns Object - Parsed tags
|
|
13
|
+
*/
|
|
14
|
+
module.exports = tags => {
|
|
15
|
+
const parsedTags = {}
|
|
16
|
+
for (const [tag, value] of Object.entries(tags)) {
|
|
17
|
+
const keys = tag.split('.')
|
|
18
|
+
let current = parsedTags
|
|
19
|
+
let depth = 0
|
|
20
|
+
for (const key of keys) {
|
|
21
|
+
if (!current[key]) {
|
|
22
|
+
if (depth === keys.length - 1) {
|
|
23
|
+
current[key] = value
|
|
24
|
+
break
|
|
25
|
+
}
|
|
26
|
+
current[key] = keys[depth + 1]?.match(digitRegex) ? [] : {}
|
|
27
|
+
}
|
|
28
|
+
current = current[key]
|
|
29
|
+
depth++
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return parsedTags
|
|
33
|
+
}
|
|
@@ -96,7 +96,9 @@ module.exports.setup = function (build) {
|
|
|
96
96
|
|
|
97
97
|
let pathToPackageJson
|
|
98
98
|
try {
|
|
99
|
-
|
|
99
|
+
// we can't use require.resolve('pkg/package.json') as ESM modules don't make the file available
|
|
100
|
+
pathToPackageJson = require.resolve(`${extracted.pkg}`, { paths: [args.resolveDir] })
|
|
101
|
+
pathToPackageJson = extractPackageAndModulePath(pathToPackageJson).pkgJson
|
|
100
102
|
} catch (err) {
|
|
101
103
|
if (err.code === 'MODULE_NOT_FOUND') {
|
|
102
104
|
if (!internal) {
|
|
@@ -111,7 +113,7 @@ module.exports.setup = function (build) {
|
|
|
111
113
|
}
|
|
112
114
|
}
|
|
113
115
|
|
|
114
|
-
const packageJson =
|
|
116
|
+
const packageJson = JSON.parse(fs.readFileSync(pathToPackageJson).toString())
|
|
115
117
|
|
|
116
118
|
if (DEBUG) console.log(`RESOLVE: ${args.path}@${packageJson.version}`)
|
|
117
119
|
|
|
@@ -25,6 +25,70 @@ addHook({ name: 'amqplib', file: 'lib/defs.js', versions: [MIN_VERSION] }, defs
|
|
|
25
25
|
return defs
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
+
addHook({ name: 'amqplib', file: 'lib/channel_model.js', versions: [MIN_VERSION] }, x => {
|
|
29
|
+
shimmer.wrap(x.Channel.prototype, 'get', getMessage => function (queue, options) {
|
|
30
|
+
return getMessage.apply(this, arguments).then(message => {
|
|
31
|
+
if (message === null) {
|
|
32
|
+
return message
|
|
33
|
+
}
|
|
34
|
+
startCh.publish({ method: 'basic.get', message, fields: message.fields, queue })
|
|
35
|
+
// finish right away
|
|
36
|
+
finishCh.publish()
|
|
37
|
+
return message
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
shimmer.wrap(x.Channel.prototype, 'consume', consume => function (queue, callback, options) {
|
|
41
|
+
if (!startCh.hasSubscribers) {
|
|
42
|
+
return consume.apply(this, arguments)
|
|
43
|
+
}
|
|
44
|
+
arguments[1] = (message, ...args) => {
|
|
45
|
+
if (message === null) {
|
|
46
|
+
return callback(message, ...args)
|
|
47
|
+
}
|
|
48
|
+
startCh.publish({ method: 'basic.deliver', message, fields: message.fields, queue })
|
|
49
|
+
const result = callback(message, ...args)
|
|
50
|
+
finishCh.publish()
|
|
51
|
+
return result
|
|
52
|
+
}
|
|
53
|
+
return consume.apply(this, arguments)
|
|
54
|
+
})
|
|
55
|
+
return x
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
addHook({ name: 'amqplib', file: 'lib/callback_model.js', versions: [MIN_VERSION] }, channel => {
|
|
59
|
+
shimmer.wrap(channel.Channel.prototype, 'get', getMessage => function (queue, options, callback) {
|
|
60
|
+
if (!startCh.hasSubscribers) {
|
|
61
|
+
return getMessage.apply(this, arguments)
|
|
62
|
+
}
|
|
63
|
+
arguments[2] = (error, message, ...args) => {
|
|
64
|
+
if (error !== null || message === null) {
|
|
65
|
+
return callback(error, message, ...args)
|
|
66
|
+
}
|
|
67
|
+
startCh.publish({ method: 'basic.get', message, fields: message.fields, queue })
|
|
68
|
+
const result = callback(error, message, ...args)
|
|
69
|
+
finishCh.publish()
|
|
70
|
+
return result
|
|
71
|
+
}
|
|
72
|
+
return getMessage.apply(this, arguments)
|
|
73
|
+
})
|
|
74
|
+
shimmer.wrap(channel.Channel.prototype, 'consume', consume => function (queue, callback) {
|
|
75
|
+
if (!startCh.hasSubscribers) {
|
|
76
|
+
return consume.apply(this, arguments)
|
|
77
|
+
}
|
|
78
|
+
arguments[1] = (message, ...args) => {
|
|
79
|
+
if (message === null) {
|
|
80
|
+
return callback(message, ...args)
|
|
81
|
+
}
|
|
82
|
+
startCh.publish({ method: 'basic.deliver', message, fields: message.fields, queue })
|
|
83
|
+
const result = callback(message, ...args)
|
|
84
|
+
finishCh.publish()
|
|
85
|
+
return result
|
|
86
|
+
}
|
|
87
|
+
return consume.apply(this, arguments)
|
|
88
|
+
})
|
|
89
|
+
return channel
|
|
90
|
+
})
|
|
91
|
+
|
|
28
92
|
addHook({ name: 'amqplib', file: 'lib/channel.js', versions: [MIN_VERSION] }, channel => {
|
|
29
93
|
shimmer.wrap(channel.Channel.prototype, 'sendImmediately', sendImmediately => function (method, fields) {
|
|
30
94
|
return instrument(sendImmediately, this, arguments, methods[method], fields)
|
|
@@ -33,15 +97,11 @@ addHook({ name: 'amqplib', file: 'lib/channel.js', versions: [MIN_VERSION] }, ch
|
|
|
33
97
|
shimmer.wrap(channel.Channel.prototype, 'sendMessage', sendMessage => function (fields) {
|
|
34
98
|
return instrument(sendMessage, this, arguments, 'basic.publish', fields, arguments[2])
|
|
35
99
|
})
|
|
36
|
-
|
|
37
|
-
shimmer.wrap(channel.BaseChannel.prototype, 'dispatchMessage', dispatchMessage => function (fields, message) {
|
|
38
|
-
return instrument(dispatchMessage, this, arguments, 'basic.deliver', fields, message)
|
|
39
|
-
})
|
|
40
100
|
return channel
|
|
41
101
|
})
|
|
42
102
|
|
|
43
103
|
function instrument (send, channel, args, method, fields, message) {
|
|
44
|
-
if (!startCh.hasSubscribers) {
|
|
104
|
+
if (!startCh.hasSubscribers || method === 'basic.get') {
|
|
45
105
|
return send.apply(channel, args)
|
|
46
106
|
}
|
|
47
107
|
|
|
@@ -13,19 +13,38 @@ const childProcessChannel = dc.tracingChannel('datadog:child_process:execution')
|
|
|
13
13
|
|
|
14
14
|
// ignored exec method because it calls to execFile directly
|
|
15
15
|
const execAsyncMethods = ['execFile', 'spawn']
|
|
16
|
-
const execSyncMethods = ['execFileSync', 'spawnSync']
|
|
17
16
|
|
|
18
17
|
const names = ['child_process', 'node:child_process']
|
|
19
18
|
|
|
20
19
|
// child_process and node:child_process returns the same object instance, we only want to add hooks once
|
|
21
20
|
let patched = false
|
|
21
|
+
|
|
22
|
+
function throwSyncError (error) {
|
|
23
|
+
throw error
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function returnSpawnSyncError (error, context) {
|
|
27
|
+
context.result = {
|
|
28
|
+
error,
|
|
29
|
+
status: null,
|
|
30
|
+
signal: null,
|
|
31
|
+
output: null,
|
|
32
|
+
stdout: null,
|
|
33
|
+
stderr: null,
|
|
34
|
+
pid: 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return context.result
|
|
38
|
+
}
|
|
39
|
+
|
|
22
40
|
names.forEach(name => {
|
|
23
41
|
addHook({ name }, childProcess => {
|
|
24
42
|
if (!patched) {
|
|
25
43
|
patched = true
|
|
26
|
-
shimmer.massWrap(childProcess, execAsyncMethods, wrapChildProcessAsyncMethod())
|
|
27
|
-
shimmer.
|
|
28
|
-
shimmer.wrap(childProcess, '
|
|
44
|
+
shimmer.massWrap(childProcess, execAsyncMethods, wrapChildProcessAsyncMethod(childProcess.ChildProcess))
|
|
45
|
+
shimmer.wrap(childProcess, 'execSync', wrapChildProcessSyncMethod(throwSyncError, true))
|
|
46
|
+
shimmer.wrap(childProcess, 'execFileSync', wrapChildProcessSyncMethod(throwSyncError))
|
|
47
|
+
shimmer.wrap(childProcess, 'spawnSync', wrapChildProcessSyncMethod(returnSpawnSyncError))
|
|
29
48
|
}
|
|
30
49
|
|
|
31
50
|
return childProcess
|
|
@@ -34,17 +53,21 @@ names.forEach(name => {
|
|
|
34
53
|
|
|
35
54
|
function normalizeArgs (args, shell) {
|
|
36
55
|
const childProcessInfo = {
|
|
37
|
-
command: args[0]
|
|
56
|
+
command: args[0],
|
|
57
|
+
file: args[0]
|
|
38
58
|
}
|
|
39
59
|
|
|
40
60
|
if (Array.isArray(args[1])) {
|
|
41
61
|
childProcessInfo.command = childProcessInfo.command + ' ' + args[1].join(' ')
|
|
62
|
+
childProcessInfo.fileArgs = args[1]
|
|
63
|
+
|
|
42
64
|
if (args[2] !== null && typeof args[2] === 'object') {
|
|
43
65
|
childProcessInfo.options = args[2]
|
|
44
66
|
}
|
|
45
67
|
} else if (args[1] !== null && typeof args[1] === 'object') {
|
|
46
68
|
childProcessInfo.options = args[1]
|
|
47
69
|
}
|
|
70
|
+
|
|
48
71
|
childProcessInfo.shell = shell ||
|
|
49
72
|
childProcessInfo.options?.shell === true ||
|
|
50
73
|
typeof childProcessInfo.options?.shell === 'string'
|
|
@@ -52,7 +75,21 @@ function normalizeArgs (args, shell) {
|
|
|
52
75
|
return childProcessInfo
|
|
53
76
|
}
|
|
54
77
|
|
|
55
|
-
function
|
|
78
|
+
function createContextFromChildProcessInfo (childProcessInfo) {
|
|
79
|
+
const context = {
|
|
80
|
+
command: childProcessInfo.command,
|
|
81
|
+
file: childProcessInfo.file,
|
|
82
|
+
shell: childProcessInfo.shell
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (childProcessInfo.fileArgs) {
|
|
86
|
+
context.fileArgs = childProcessInfo.fileArgs
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return context
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function wrapChildProcessSyncMethod (returnError, shell = false) {
|
|
56
93
|
return function wrapMethod (childProcessMethod) {
|
|
57
94
|
return function () {
|
|
58
95
|
if (!childProcessChannel.start.hasSubscribers || arguments.length === 0) {
|
|
@@ -63,14 +100,30 @@ function wrapChildProcessSyncMethod (shell = false) {
|
|
|
63
100
|
|
|
64
101
|
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
65
102
|
return innerResource.runInAsyncScope(() => {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
103
|
+
const context = createContextFromChildProcessInfo(childProcessInfo)
|
|
104
|
+
const abortController = new AbortController()
|
|
105
|
+
|
|
106
|
+
childProcessChannel.start.publish({ ...context, abortController })
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
if (abortController.signal.aborted) {
|
|
110
|
+
const error = abortController.signal.reason || new Error('Aborted')
|
|
111
|
+
// expected behaviors on error are different
|
|
112
|
+
return returnError(error, context)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const result = childProcessMethod.apply(this, arguments)
|
|
116
|
+
context.result = result
|
|
117
|
+
|
|
118
|
+
return result
|
|
119
|
+
} catch (err) {
|
|
120
|
+
context.error = err
|
|
121
|
+
childProcessChannel.error.publish(context)
|
|
122
|
+
|
|
123
|
+
throw err
|
|
124
|
+
} finally {
|
|
125
|
+
childProcessChannel.end.publish(context)
|
|
126
|
+
}
|
|
74
127
|
})
|
|
75
128
|
}
|
|
76
129
|
}
|
|
@@ -84,18 +137,52 @@ function wrapChildProcessCustomPromisifyMethod (customPromisifyMethod, shell) {
|
|
|
84
137
|
|
|
85
138
|
const childProcessInfo = normalizeArgs(arguments, shell)
|
|
86
139
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
140
|
+
const context = createContextFromChildProcessInfo(childProcessInfo)
|
|
141
|
+
|
|
142
|
+
const { start, end, asyncStart, asyncEnd, error } = childProcessChannel
|
|
143
|
+
const abortController = new AbortController()
|
|
144
|
+
|
|
145
|
+
start.publish({
|
|
146
|
+
...context,
|
|
147
|
+
abortController
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
let result
|
|
151
|
+
if (abortController.signal.aborted) {
|
|
152
|
+
result = Promise.reject(abortController.signal.reason || new Error('Aborted'))
|
|
153
|
+
} else {
|
|
154
|
+
try {
|
|
155
|
+
result = customPromisifyMethod.apply(this, arguments)
|
|
156
|
+
} catch (error) {
|
|
157
|
+
error.publish({ ...context, error })
|
|
158
|
+
throw error
|
|
159
|
+
} finally {
|
|
160
|
+
end.publish(context)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function reject (err) {
|
|
165
|
+
context.error = err
|
|
166
|
+
error.publish(context)
|
|
167
|
+
asyncStart.publish(context)
|
|
168
|
+
|
|
169
|
+
asyncEnd.publish(context)
|
|
170
|
+
return Promise.reject(err)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function resolve (result) {
|
|
174
|
+
context.result = result
|
|
175
|
+
asyncStart.publish(context)
|
|
176
|
+
|
|
177
|
+
asyncEnd.publish(context)
|
|
178
|
+
return result
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return Promise.prototype.then.call(result, resolve, reject)
|
|
95
182
|
}
|
|
96
183
|
}
|
|
97
184
|
|
|
98
|
-
function wrapChildProcessAsyncMethod (shell = false) {
|
|
185
|
+
function wrapChildProcessAsyncMethod (ChildProcess, shell = false) {
|
|
99
186
|
return function wrapMethod (childProcessMethod) {
|
|
100
187
|
function wrappedChildProcessMethod () {
|
|
101
188
|
if (!childProcessChannel.start.hasSubscribers || arguments.length === 0) {
|
|
@@ -112,9 +199,31 @@ function wrapChildProcessAsyncMethod (shell = false) {
|
|
|
112
199
|
|
|
113
200
|
const innerResource = new AsyncResource('bound-anonymous-fn')
|
|
114
201
|
return innerResource.runInAsyncScope(() => {
|
|
115
|
-
|
|
202
|
+
const context = createContextFromChildProcessInfo(childProcessInfo)
|
|
203
|
+
const abortController = new AbortController()
|
|
204
|
+
|
|
205
|
+
childProcessChannel.start.publish({ ...context, abortController })
|
|
206
|
+
|
|
207
|
+
let childProcess
|
|
208
|
+
if (abortController.signal.aborted) {
|
|
209
|
+
childProcess = new ChildProcess()
|
|
210
|
+
childProcess.on('error', () => {}) // Original method does not crash when non subscribers
|
|
211
|
+
|
|
212
|
+
process.nextTick(() => {
|
|
213
|
+
const error = abortController.signal.reason || new Error('Aborted')
|
|
214
|
+
childProcess.emit('error', error)
|
|
215
|
+
|
|
216
|
+
const cb = arguments[arguments.length - 1]
|
|
217
|
+
if (typeof cb === 'function') {
|
|
218
|
+
cb(error)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
childProcess.emit('close')
|
|
222
|
+
})
|
|
223
|
+
} else {
|
|
224
|
+
childProcess = childProcessMethod.apply(this, arguments)
|
|
225
|
+
}
|
|
116
226
|
|
|
117
|
-
const childProcess = childProcessMethod.apply(this, arguments)
|
|
118
227
|
if (childProcess) {
|
|
119
228
|
let errorExecuted = false
|
|
120
229
|
|
|
@@ -129,8 +238,7 @@ function wrapChildProcessAsyncMethod (shell = false) {
|
|
|
129
238
|
childProcessChannel.error.publish()
|
|
130
239
|
}
|
|
131
240
|
childProcessChannel.asyncEnd.publish({
|
|
132
|
-
|
|
133
|
-
shell: childProcessInfo.shell,
|
|
241
|
+
...context,
|
|
134
242
|
result: code
|
|
135
243
|
})
|
|
136
244
|
})
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const handlebarsCompileCh = channel('datadog:handlebars:compile:start')
|
|
7
|
+
const handlebarsRegisterPartialCh = channel('datadog:handlebars:register-partial:start')
|
|
8
|
+
|
|
9
|
+
function wrapCompile (compile) {
|
|
10
|
+
return function wrappedCompile (source) {
|
|
11
|
+
if (handlebarsCompileCh.hasSubscribers) {
|
|
12
|
+
handlebarsCompileCh.publish({ source })
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return compile.apply(this, arguments)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function wrapRegisterPartial (registerPartial) {
|
|
20
|
+
return function wrappedRegisterPartial (name, partial) {
|
|
21
|
+
if (handlebarsRegisterPartialCh.hasSubscribers) {
|
|
22
|
+
handlebarsRegisterPartialCh.publish({ partial })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return registerPartial.apply(this, arguments)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
addHook({ name: 'handlebars', file: 'dist/cjs/handlebars/compiler/compiler.js', versions: ['>=4.0.0'] }, compiler => {
|
|
30
|
+
shimmer.wrap(compiler, 'compile', wrapCompile)
|
|
31
|
+
shimmer.wrap(compiler, 'precompile', wrapCompile)
|
|
32
|
+
|
|
33
|
+
return compiler
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
addHook({ name: 'handlebars', file: 'dist/cjs/handlebars/base.js', versions: ['>=4.0.0'] }, base => {
|
|
37
|
+
shimmer.wrap(base.HandlebarsEnvironment.prototype, 'registerPartial', wrapRegisterPartial)
|
|
38
|
+
|
|
39
|
+
return base
|
|
40
|
+
})
|
|
@@ -51,6 +51,7 @@ module.exports = {
|
|
|
51
51
|
'generic-pool': () => require('../generic-pool'),
|
|
52
52
|
graphql: () => require('../graphql'),
|
|
53
53
|
grpc: () => require('../grpc'),
|
|
54
|
+
handlebars: () => require('../handlebars'),
|
|
54
55
|
hapi: () => require('../hapi'),
|
|
55
56
|
http: () => require('../http'),
|
|
56
57
|
http2: () => require('../http2'),
|
|
@@ -79,6 +80,7 @@ module.exports = {
|
|
|
79
80
|
'mongodb-core': () => require('../mongodb-core'),
|
|
80
81
|
mongoose: () => require('../mongoose'),
|
|
81
82
|
mquery: () => require('../mquery'),
|
|
83
|
+
multer: () => require('../multer'),
|
|
82
84
|
mysql: () => require('../mysql'),
|
|
83
85
|
mysql2: () => require('../mysql2'),
|
|
84
86
|
net: () => require('../net'),
|
|
@@ -90,6 +92,7 @@ module.exports = {
|
|
|
90
92
|
'node:http2': () => require('../http2'),
|
|
91
93
|
'node:https': () => require('../http'),
|
|
92
94
|
'node:net': () => require('../net'),
|
|
95
|
+
'node:url': () => require('../url'),
|
|
93
96
|
nyc: () => require('../nyc'),
|
|
94
97
|
oracledb: () => require('../oracledb'),
|
|
95
98
|
openai: () => require('../openai'),
|
|
@@ -103,6 +106,7 @@ module.exports = {
|
|
|
103
106
|
'promise-js': () => require('../promise-js'),
|
|
104
107
|
promise: () => require('../promise'),
|
|
105
108
|
protobufjs: () => require('../protobufjs'),
|
|
109
|
+
pug: () => require('../pug'),
|
|
106
110
|
q: () => require('../q'),
|
|
107
111
|
qs: () => require('../qs'),
|
|
108
112
|
redis: () => require('../redis'),
|
|
@@ -114,6 +118,7 @@ module.exports = {
|
|
|
114
118
|
sharedb: () => require('../sharedb'),
|
|
115
119
|
tedious: () => require('../tedious'),
|
|
116
120
|
undici: () => require('../undici'),
|
|
121
|
+
url: () => require('../url'),
|
|
117
122
|
vitest: { esmFirst: true, fn: () => require('../vitest') },
|
|
118
123
|
when: () => require('../when'),
|
|
119
124
|
winston: () => require('../winston'),
|
|
@@ -22,6 +22,15 @@ const disabledInstrumentations = new Set(
|
|
|
22
22
|
DD_TRACE_DISABLED_INSTRUMENTATIONS ? DD_TRACE_DISABLED_INSTRUMENTATIONS.split(',') : []
|
|
23
23
|
)
|
|
24
24
|
|
|
25
|
+
// Check for DD_TRACE_<INTEGRATION>_ENABLED environment variables
|
|
26
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
27
|
+
const match = key.match(/^DD_TRACE_(.+)_ENABLED$/)
|
|
28
|
+
if (match && (value.toLowerCase() === 'false' || value === '0')) {
|
|
29
|
+
const integration = match[1].toLowerCase()
|
|
30
|
+
disabledInstrumentations.add(integration)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
const loadChannel = channel('dd-trace:instrumentation:load')
|
|
26
35
|
|
|
27
36
|
// Globals
|
|
@@ -127,6 +127,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
127
127
|
|
|
128
128
|
if (repositoryRoot) {
|
|
129
129
|
this.testSourceFile = getTestSuitePath(context.testPath, repositoryRoot)
|
|
130
|
+
this.repositoryRoot = repositoryRoot
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
this.isEarlyFlakeDetectionEnabled = this.testEnvironmentOptions._ddIsEarlyFlakeDetectionEnabled
|
|
@@ -667,10 +668,13 @@ function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
|
667
668
|
* controls whether coverage is reported.
|
|
668
669
|
*/
|
|
669
670
|
if (environment.testEnvironmentOptions?._ddTestCodeCoverageEnabled) {
|
|
671
|
+
const root = environment.repositoryRoot || environment.rootDir
|
|
672
|
+
|
|
670
673
|
const coverageFiles = getCoveredFilenamesFromCoverage(environment.global.__coverage__)
|
|
671
|
-
.map(filename => getTestSuitePath(filename,
|
|
674
|
+
.map(filename => getTestSuitePath(filename, root))
|
|
675
|
+
|
|
672
676
|
asyncResource.runInAsyncScope(() => {
|
|
673
|
-
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.
|
|
677
|
+
testSuiteCodeCoverageCh.publish({ coverageFiles, testSuite: environment.testSourceFile })
|
|
674
678
|
})
|
|
675
679
|
}
|
|
676
680
|
testSuiteFinishCh.publish({ status, errorMessage })
|