dd-trace 5.67.0 → 5.69.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 +6 -4
- package/README.md +0 -2
- package/ci/init.js +52 -54
- package/ext/exporters.d.ts +2 -1
- package/ext/exporters.js +2 -1
- package/index.d.ts +240 -3
- package/initialize.mjs +1 -1
- package/package.json +17 -11
- package/packages/datadog-core/src/storage.js +14 -13
- package/packages/datadog-esbuild/index.js +118 -26
- package/packages/datadog-instrumentations/src/aws-sdk.js +42 -4
- package/packages/datadog-instrumentations/src/azure-functions.js +1 -1
- package/packages/datadog-instrumentations/src/azure-service-bus.js +1 -1
- package/packages/datadog-instrumentations/src/cassandra-driver.js +2 -2
- package/packages/datadog-instrumentations/src/connect.js +6 -2
- package/packages/datadog-instrumentations/src/cucumber.js +31 -6
- package/packages/datadog-instrumentations/src/express.js +5 -6
- package/packages/datadog-instrumentations/src/fastify.js +3 -3
- package/packages/datadog-instrumentations/src/helpers/hook.js +28 -15
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +15 -5
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -3
- package/packages/datadog-instrumentations/src/http2/client.js +1 -0
- package/packages/datadog-instrumentations/src/http2/server.js +0 -1
- package/packages/datadog-instrumentations/src/ioredis.js +12 -1
- package/packages/datadog-instrumentations/src/jest.js +48 -36
- package/packages/datadog-instrumentations/src/limitd-client.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/main.js +15 -7
- package/packages/datadog-instrumentations/src/mocha/utils.js +3 -0
- package/packages/datadog-instrumentations/src/mongoose.js +2 -1
- package/packages/datadog-instrumentations/src/oracledb.js +19 -13
- package/packages/datadog-instrumentations/src/pg.js +9 -5
- package/packages/datadog-instrumentations/src/pino.js +18 -6
- package/packages/datadog-instrumentations/src/playwright.js +15 -1
- package/packages/datadog-instrumentations/src/sequelize.js +1 -1
- package/packages/datadog-instrumentations/src/vitest.js +155 -62
- package/packages/datadog-plugin-ai/src/tracing.js +3 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +23 -8
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/tracing.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +101 -2
- package/packages/datadog-plugin-aws-sdk/src/util.js +1 -1
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +6 -0
- package/packages/datadog-plugin-cucumber/src/index.js +4 -56
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +6 -3
- package/packages/datadog-plugin-cypress/src/support.js +4 -0
- package/packages/datadog-plugin-express/src/code_origin.js +2 -2
- package/packages/datadog-plugin-fastify/src/code_origin.js +1 -2
- package/packages/datadog-plugin-jest/src/index.js +0 -21
- package/packages/datadog-plugin-mocha/src/index.js +3 -57
- package/packages/datadog-plugin-mongodb-core/src/index.js +38 -12
- package/packages/datadog-plugin-playwright/src/index.js +11 -5
- package/packages/datadog-plugin-vitest/src/index.js +5 -1
- package/packages/datadog-plugin-ws/src/close.js +1 -1
- package/packages/datadog-plugin-ws/src/producer.js +6 -1
- package/packages/datadog-plugin-ws/src/receiver.js +6 -1
- package/packages/dd-trace/src/aiguard/client.js +25 -0
- package/packages/dd-trace/src/aiguard/noop.js +9 -0
- package/packages/dd-trace/src/aiguard/sdk.js +173 -0
- package/packages/dd-trace/src/aiguard/tags.js +11 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +21 -4
- package/packages/dd-trace/src/appsec/iast/security-controls/parser.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +6 -3
- package/packages/dd-trace/src/appsec/stack_trace.js +20 -1
- package/packages/dd-trace/src/appsec/telemetry/waf.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -4
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +11 -3
- package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +10 -1
- package/packages/dd-trace/src/config-helper.js +8 -1
- package/packages/dd-trace/src/config.js +92 -304
- package/packages/dd-trace/src/config_defaults.js +191 -0
- package/packages/dd-trace/src/crashtracking/crashtracker.js +2 -1
- package/packages/dd-trace/src/datastreams/fnv.js +2 -2
- package/packages/dd-trace/src/datastreams/index.js +23 -1
- package/packages/dd-trace/src/datastreams/writer.js +3 -2
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -1
- package/packages/dd-trace/src/dogstatsd.js +4 -3
- package/packages/dd-trace/src/encode/0.4.js +1 -5
- package/packages/dd-trace/src/exporter.js +1 -0
- package/packages/dd-trace/src/exporters/agent/index.js +3 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +3 -2
- package/packages/dd-trace/src/exporters/common/request.js +2 -1
- package/packages/dd-trace/src/exporters/span-stats/index.js +3 -2
- package/packages/dd-trace/src/llmobs/constants/tags.js +2 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +15 -4
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +20 -7
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +40 -13
- package/packages/dd-trace/src/llmobs/plugins/openai.js +7 -1
- package/packages/dd-trace/src/llmobs/tagger.js +8 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +2 -1
- package/packages/dd-trace/src/log/index.js +27 -16
- package/packages/dd-trace/src/log/log.js +29 -5
- package/packages/dd-trace/src/log/writer.js +5 -5
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +14 -3
- package/packages/dd-trace/src/opentracing/span.js +19 -5
- package/packages/dd-trace/src/payload-tagging/config/index.js +16 -0
- package/packages/dd-trace/src/payload-tagging/index.js +26 -15
- package/packages/dd-trace/src/payload-tagging/tagging.js +17 -8
- package/packages/dd-trace/src/pkg.js +3 -1
- package/packages/dd-trace/src/plugin_manager.js +20 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +97 -3
- package/packages/dd-trace/src/plugins/composite.js +3 -0
- package/packages/dd-trace/src/plugins/index.js +2 -0
- package/packages/dd-trace/src/plugins/plugin.js +67 -0
- package/packages/dd-trace/src/plugins/util/git-cache.js +129 -0
- package/packages/dd-trace/src/plugins/util/git.js +41 -27
- package/packages/dd-trace/src/plugins/util/test.js +56 -27
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +70 -46
- package/packages/dd-trace/src/profiler.js +4 -1
- package/packages/dd-trace/src/profiling/config.js +73 -42
- package/packages/dd-trace/src/profiling/profiler.js +3 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -8
- package/packages/dd-trace/src/profiling/profilers/space.js +1 -0
- package/packages/dd-trace/src/profiling/profilers/wall.js +196 -117
- package/packages/dd-trace/src/proxy.js +15 -0
- package/packages/dd-trace/src/rate_limiter.js +26 -1
- package/packages/dd-trace/src/remote_config/capabilities.js +5 -0
- package/packages/dd-trace/src/remote_config/manager.js +3 -2
- package/packages/dd-trace/src/sampling_rule.js +124 -2
- package/packages/dd-trace/src/span_sampler.js +19 -0
- package/packages/dd-trace/src/standalone/product.js +9 -0
- package/packages/dd-trace/src/standalone/tracesource.js +16 -1
- package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +13 -0
- package/packages/dd-trace/src/startup-log.js +21 -2
- package/packages/dd-trace/src/supported-configurations.json +9 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/util.js +1 -1
- package/register.js +1 -1
- package/version.js +4 -2
|
@@ -10,12 +10,13 @@ const { AsyncLocalStorage } = require('async_hooks')
|
|
|
10
10
|
* a "handle" object, which is used as a key in a WeakMap, where the values
|
|
11
11
|
* are the real store objects.
|
|
12
12
|
*
|
|
13
|
-
* @
|
|
13
|
+
* @typedef {Record<string, unknown>} Store
|
|
14
14
|
*/
|
|
15
15
|
class DatadogStorage extends AsyncLocalStorage {
|
|
16
16
|
/**
|
|
17
17
|
*
|
|
18
|
-
* @param store {
|
|
18
|
+
* @param store {Store}
|
|
19
|
+
* @override
|
|
19
20
|
*/
|
|
20
21
|
enterWith (store) {
|
|
21
22
|
const handle = {}
|
|
@@ -34,7 +35,7 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
34
35
|
*
|
|
35
36
|
* TODO: Refactor the Scope class to use a span-only store and remove this.
|
|
36
37
|
*
|
|
37
|
-
* @returns {
|
|
38
|
+
* @returns {Store}
|
|
38
39
|
*/
|
|
39
40
|
getHandle () {
|
|
40
41
|
return super.getStore()
|
|
@@ -46,9 +47,9 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
46
47
|
* retrieved through `getHandle()` can also be passed in to be used as the
|
|
47
48
|
* key. This is useful if you've stashed a handle somewhere and want to
|
|
48
49
|
* retrieve the store with it.
|
|
49
|
-
*
|
|
50
|
-
* @
|
|
51
|
-
* @
|
|
50
|
+
* @param {{}} [handle]
|
|
51
|
+
* @returns {Store | undefined}
|
|
52
|
+
* @override
|
|
52
53
|
*/
|
|
53
54
|
getStore (handle) {
|
|
54
55
|
if (!handle) {
|
|
@@ -66,11 +67,12 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
66
67
|
* when dealing with the parent store, so that we don't have to access the
|
|
67
68
|
* WeakMap.
|
|
68
69
|
* @template R
|
|
69
|
-
* @template TArgs
|
|
70
|
-
* @param
|
|
71
|
-
* @param
|
|
72
|
-
* @param
|
|
73
|
-
* @returns {
|
|
70
|
+
* @template TArgs = unknown[]
|
|
71
|
+
* @param {Store} store
|
|
72
|
+
* @param {() => R} fn
|
|
73
|
+
* @param {...TArgs} args
|
|
74
|
+
* @returns {R}
|
|
75
|
+
* @override
|
|
74
76
|
*/
|
|
75
77
|
run (store, fn, ...args) {
|
|
76
78
|
const prior = super.getStore()
|
|
@@ -85,8 +87,7 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
85
87
|
|
|
86
88
|
/**
|
|
87
89
|
* This is the map from handles to real stores, used in the class above.
|
|
88
|
-
* @
|
|
89
|
-
* @type {WeakMap<WeakKey, T>}
|
|
90
|
+
* @type {WeakMap<WeakKey, Store>}
|
|
90
91
|
*/
|
|
91
92
|
const stores = new WeakMap()
|
|
92
93
|
|
|
@@ -8,6 +8,8 @@ const extractPackageAndModulePath = require(
|
|
|
8
8
|
'../datadog-instrumentations/src/helpers/extract-package-and-module-path.js'
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
+
let rewriter
|
|
12
|
+
|
|
11
13
|
for (const hook of Object.values(hooks)) {
|
|
12
14
|
if (typeof hook === 'object') {
|
|
13
15
|
hook.fn()
|
|
@@ -33,6 +35,7 @@ const RAW_BUILTINS = require('module').builtinModules
|
|
|
33
35
|
const CHANNEL = 'dd-trace:bundler:load'
|
|
34
36
|
const path = require('path')
|
|
35
37
|
const fs = require('fs')
|
|
38
|
+
const { execSync } = require('child_process')
|
|
36
39
|
|
|
37
40
|
const builtins = new Set()
|
|
38
41
|
|
|
@@ -42,6 +45,7 @@ for (const builtin of RAW_BUILTINS) {
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
const DEBUG = !!process.env.DD_TRACE_DEBUG
|
|
48
|
+
const DD_IAST_ENABLED = process.env.DD_IAST_ENABLED?.toLowerCase() === 'true' || process.env.DD_IAST_ENABLED === '1'
|
|
45
49
|
|
|
46
50
|
// We don't want to handle any built-in packages
|
|
47
51
|
// Those packages will still be handled via RITM
|
|
@@ -61,11 +65,57 @@ function isESMBuild (build) {
|
|
|
61
65
|
return format === 'esm' || outputFile?.endsWith('.mjs') || outExtension === '.mjs'
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
function getGitMetadata () {
|
|
69
|
+
const gitMetadata = {
|
|
70
|
+
repositoryURL: null,
|
|
71
|
+
commitSHA: null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
gitMetadata.repositoryURL = execSync('git config --get remote.origin.url', {
|
|
76
|
+
encoding: 'utf8',
|
|
77
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
78
|
+
cwd: process.cwd()
|
|
79
|
+
}).trim()
|
|
80
|
+
} catch (e) {
|
|
81
|
+
if (DEBUG) {
|
|
82
|
+
console.warn('Warning: failed to get git repository URL:', e.message)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
gitMetadata.commitSHA = execSync('git rev-parse HEAD', {
|
|
88
|
+
encoding: 'utf8',
|
|
89
|
+
stdio: ['pipe', 'pipe', 'ignore'],
|
|
90
|
+
cwd: process.cwd()
|
|
91
|
+
}).trim()
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (DEBUG) {
|
|
94
|
+
console.warn('Warning: failed to get git commit SHA:', e.message)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return gitMetadata
|
|
99
|
+
}
|
|
100
|
+
|
|
64
101
|
module.exports.setup = function (build) {
|
|
102
|
+
if (DD_IAST_ENABLED) {
|
|
103
|
+
const iastRewriter = require('../dd-trace/src/appsec/iast/taint-tracking/rewriter')
|
|
104
|
+
rewriter = iastRewriter.getRewriter()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const isSourceMapEnabled = !!build.initialOptions.sourcemap ||
|
|
108
|
+
['internal', 'both'].includes(build.initialOptions.sourcemap)
|
|
65
109
|
const externalModules = new Set(build.initialOptions.external || [])
|
|
110
|
+
build.initialOptions.banner ??= {}
|
|
111
|
+
build.initialOptions.banner.js ??= ''
|
|
112
|
+
if (DD_IAST_ENABLED) {
|
|
113
|
+
build.initialOptions.banner.js =
|
|
114
|
+
`globalThis.__DD_ESBUILD_IAST_${isSourceMapEnabled ? 'WITH_SM' : 'WITH_NO_SM'} = true;
|
|
115
|
+
${isSourceMapEnabled ? `globalThis.__DD_ESBUILD_BASEPATH = '${require('../dd-trace/src/util').ddBasePath}';` : ''}
|
|
116
|
+
${build.initialOptions.banner.js}`
|
|
117
|
+
}
|
|
66
118
|
if (isESMBuild(build)) {
|
|
67
|
-
build.initialOptions.banner ??= {}
|
|
68
|
-
build.initialOptions.banner.js ??= ''
|
|
69
119
|
if (!build.initialOptions.banner.js.includes('import { createRequire as $dd_createRequire } from \'module\'')) {
|
|
70
120
|
build.initialOptions.banner.js = `import { createRequire as $dd_createRequire } from 'module';
|
|
71
121
|
import { fileURLToPath as $dd_fileURLToPath } from 'url';
|
|
@@ -77,6 +127,28 @@ ${build.initialOptions.banner.js}`
|
|
|
77
127
|
}
|
|
78
128
|
}
|
|
79
129
|
|
|
130
|
+
// Get git metadata at build time and add it to the banner for both ESM and CommonJS builds
|
|
131
|
+
const gitMetadata = getGitMetadata()
|
|
132
|
+
if (gitMetadata.repositoryURL || gitMetadata.commitSHA) {
|
|
133
|
+
build.initialOptions.banner ??= {}
|
|
134
|
+
build.initialOptions.banner.js ??= ''
|
|
135
|
+
|
|
136
|
+
build.initialOptions.banner.js = `if (typeof process === 'object' && process !== null &&
|
|
137
|
+
process.env !== null && typeof process.env === 'object') {
|
|
138
|
+
${gitMetadata.repositoryURL ? `process.env.DD_GIT_REPOSITORY_URL = '${gitMetadata.repositoryURL}';` : ''}
|
|
139
|
+
${gitMetadata.commitSHA ? `process.env.DD_GIT_COMMIT_SHA = '${gitMetadata.commitSHA}';` : ''}
|
|
140
|
+
}
|
|
141
|
+
${build.initialOptions.banner.js}`
|
|
142
|
+
|
|
143
|
+
if (DEBUG) {
|
|
144
|
+
console.log('Info: automatically injected git metadata:')
|
|
145
|
+
console.log(`DD_GIT_REPOSITORY_URL: ${gitMetadata.repositoryURL || 'not available'}`)
|
|
146
|
+
console.log(`DD_GIT_COMMIT_SHA: ${gitMetadata.commitSHA || 'not available'}`)
|
|
147
|
+
}
|
|
148
|
+
} else if (DEBUG) {
|
|
149
|
+
console.warn('Warning: No git metadata available - skipping injection')
|
|
150
|
+
}
|
|
151
|
+
|
|
80
152
|
build.onResolve({ filter: /.*/ }, args => {
|
|
81
153
|
if (externalModules.has(args.path)) {
|
|
82
154
|
// Internal Node.js packages will still be instrumented via require()
|
|
@@ -84,13 +156,6 @@ ${build.initialOptions.banner.js}`
|
|
|
84
156
|
return
|
|
85
157
|
}
|
|
86
158
|
|
|
87
|
-
// TODO: Should this also check for namespace === 'file'?
|
|
88
|
-
if (args.path.startsWith('.') && !args.importer.includes('node_modules/')) {
|
|
89
|
-
// This is local application code, not an instrumented package
|
|
90
|
-
if (DEBUG) console.log(`LOCAL: ${args.path}`)
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
|
|
94
159
|
// TODO: Should this also check for namespace === 'file'?
|
|
95
160
|
if (!modulesOfInterest.has(args.path) &&
|
|
96
161
|
args.path.startsWith('@') &&
|
|
@@ -110,6 +175,21 @@ ${build.initialOptions.banner.js}`
|
|
|
110
175
|
}
|
|
111
176
|
return
|
|
112
177
|
}
|
|
178
|
+
|
|
179
|
+
if (args.path.startsWith('.') && !args.importer.includes('node_modules/')) {
|
|
180
|
+
// It is local application code, not an instrumented package
|
|
181
|
+
if (DEBUG) console.log(`APP: ${args.path}`)
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
path: fullPathToModule,
|
|
185
|
+
pluginData: {
|
|
186
|
+
path: args.path,
|
|
187
|
+
full: fullPathToModule,
|
|
188
|
+
applicationFile: true
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
113
193
|
const extracted = extractPackageAndModulePath(fullPathToModule)
|
|
114
194
|
|
|
115
195
|
const internal = builtins.has(args.path)
|
|
@@ -159,22 +239,19 @@ ${build.initialOptions.banner.js}`
|
|
|
159
239
|
})
|
|
160
240
|
|
|
161
241
|
build.onLoad({ filter: /.*/ }, args => {
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const data = args.pluginData
|
|
242
|
+
if (args.pluginData?.pkgOfInterest) {
|
|
243
|
+
const data = args.pluginData
|
|
167
244
|
|
|
168
|
-
|
|
245
|
+
if (DEBUG) console.log(`LOAD: ${data.pkg}@${data.version}, pkg "${data.path}"`)
|
|
169
246
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
247
|
+
const pkgPath = data.raw !== data.pkg
|
|
248
|
+
? `${data.pkg}/${data.path}`
|
|
249
|
+
: data.pkg
|
|
173
250
|
|
|
174
|
-
|
|
175
|
-
|
|
251
|
+
// Read the content of the module file of interest
|
|
252
|
+
const fileCode = fs.readFileSync(args.path, 'utf8')
|
|
176
253
|
|
|
177
|
-
|
|
254
|
+
const contents = `
|
|
178
255
|
(function() {
|
|
179
256
|
${fileCode}
|
|
180
257
|
})(...arguments);
|
|
@@ -192,12 +269,27 @@ ${build.initialOptions.banner.js}`
|
|
|
192
269
|
module.exports = payload.module;
|
|
193
270
|
}
|
|
194
271
|
`
|
|
272
|
+
// https://esbuild.github.io/plugins/#on-load-results
|
|
273
|
+
return {
|
|
274
|
+
contents,
|
|
275
|
+
loader: 'js',
|
|
276
|
+
resolveDir: path.dirname(args.path)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
195
279
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
280
|
+
if (DD_IAST_ENABLED && args.pluginData?.applicationFile) {
|
|
281
|
+
const ext = path.extname(args.path).toLowerCase()
|
|
282
|
+
const isJs = /^\.(js|mjs|cjs)$/.test(ext)
|
|
283
|
+
if (!isJs) return
|
|
284
|
+
|
|
285
|
+
if (DEBUG) console.log(`REWRITE: ${args.path}`)
|
|
286
|
+
const fileCode = fs.readFileSync(args.path, 'utf8')
|
|
287
|
+
const rewritten = rewriter.rewrite(fileCode, args.path, ['iast'])
|
|
288
|
+
return {
|
|
289
|
+
contents: rewritten.content,
|
|
290
|
+
loader: 'js',
|
|
291
|
+
resolveDir: path.dirname(args.path)
|
|
292
|
+
}
|
|
201
293
|
}
|
|
202
294
|
})
|
|
203
295
|
}
|
|
@@ -61,7 +61,6 @@ function wrapSmithySend (send) {
|
|
|
61
61
|
|
|
62
62
|
const startCh = channel(`apm:aws:request:start:${channelSuffix}`)
|
|
63
63
|
const regionCh = channel(`apm:aws:request:region:${channelSuffix}`)
|
|
64
|
-
const completeChannel = channel(`apm:aws:request:complete:${channelSuffix}`)
|
|
65
64
|
const responseStartChannel = channel(`apm:aws:response:start:${channelSuffix}`)
|
|
66
65
|
const responseFinishChannel = channel(`apm:aws:response:finish:${channelSuffix}`)
|
|
67
66
|
|
|
@@ -87,7 +86,7 @@ function wrapSmithySend (send) {
|
|
|
87
86
|
args[args.length - 1] = shimmer.wrapFunction(cb, cb => function (err, result) {
|
|
88
87
|
addResponse(ctx, err, result)
|
|
89
88
|
|
|
90
|
-
|
|
89
|
+
handleCompletion(result, ctx, channelSuffix)
|
|
91
90
|
|
|
92
91
|
const responseCtx = { request, response: ctx.response }
|
|
93
92
|
|
|
@@ -102,12 +101,12 @@ function wrapSmithySend (send) {
|
|
|
102
101
|
.then(
|
|
103
102
|
result => {
|
|
104
103
|
addResponse(ctx, null, result)
|
|
105
|
-
|
|
104
|
+
handleCompletion(result, ctx, channelSuffix)
|
|
106
105
|
return result
|
|
107
106
|
},
|
|
108
107
|
error => {
|
|
109
108
|
addResponse(ctx, error)
|
|
110
|
-
|
|
109
|
+
handleCompletion(null, ctx, channelSuffix)
|
|
111
110
|
throw error
|
|
112
111
|
}
|
|
113
112
|
)
|
|
@@ -118,6 +117,45 @@ function wrapSmithySend (send) {
|
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
|
|
120
|
+
function handleCompletion (result, ctx, channelSuffix) {
|
|
121
|
+
const completeChannel = channel(`apm:aws:request:complete:${channelSuffix}`)
|
|
122
|
+
const streamedChunkChannel = channel(`apm:aws:response:streamed-chunk:${channelSuffix}`)
|
|
123
|
+
|
|
124
|
+
const iterator = result?.body?.[Symbol.asyncIterator]
|
|
125
|
+
if (!iterator) {
|
|
126
|
+
completeChannel.publish(ctx)
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
shimmer.wrap(result.body, Symbol.asyncIterator, function (asyncIterator) {
|
|
131
|
+
return function () {
|
|
132
|
+
const iterator = asyncIterator.apply(this, arguments)
|
|
133
|
+
shimmer.wrap(iterator, 'next', function (next) {
|
|
134
|
+
return function () {
|
|
135
|
+
return next.apply(this, arguments)
|
|
136
|
+
.then(result => {
|
|
137
|
+
const { done, value: chunk } = result
|
|
138
|
+
streamedChunkChannel.publish({ ctx, chunk, done })
|
|
139
|
+
|
|
140
|
+
if (done) {
|
|
141
|
+
completeChannel.publish(ctx)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return result
|
|
145
|
+
})
|
|
146
|
+
.catch(err => {
|
|
147
|
+
addResponse(ctx, err)
|
|
148
|
+
completeChannel.publish(ctx)
|
|
149
|
+
throw err
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
return iterator
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
121
159
|
function wrapCb (cb, serviceName, ctx) {
|
|
122
160
|
// eslint-disable-next-line n/handle-callback-err
|
|
123
161
|
return shimmer.wrapFunction(cb, cb => function wrappedCb (err, response) {
|
|
@@ -8,7 +8,7 @@ const dc = require('dc-polyfill')
|
|
|
8
8
|
|
|
9
9
|
const azureFunctionsChannel = dc.tracingChannel('datadog:azure:functions:invoke')
|
|
10
10
|
|
|
11
|
-
addHook({ name: '@azure/functions', versions: ['>=4'] }, azureFunction => {
|
|
11
|
+
addHook({ name: '@azure/functions', versions: ['>=4'], patchDefault: false }, (azureFunction) => {
|
|
12
12
|
const { app } = azureFunction
|
|
13
13
|
|
|
14
14
|
// Http triggers
|
|
@@ -11,7 +11,7 @@ const producerStartCh = channel('apm:azure-service-bus:send:start')
|
|
|
11
11
|
const producerErrorCh = channel('apm:azure-service-bus:send:error')
|
|
12
12
|
const producerFinishCh = channel('apm:azure-service-bus:send:finish')
|
|
13
13
|
|
|
14
|
-
addHook({ name: '@azure/service-bus', versions: ['>=7.9.2'] }, (obj) => {
|
|
14
|
+
addHook({ name: '@azure/service-bus', versions: ['>=7.9.2'], patchDefault: false }, (obj) => {
|
|
15
15
|
const ServiceBusClient = obj.ServiceBusClient
|
|
16
16
|
shimmer.wrap(ServiceBusClient.prototype, 'createSender', createSender => function (queueOrTopicName) {
|
|
17
17
|
const sender = createSender.apply(this, arguments)
|
|
@@ -45,7 +45,7 @@ addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
|
|
|
45
45
|
return cassandra
|
|
46
46
|
})
|
|
47
47
|
|
|
48
|
-
addHook({ name: 'cassandra-driver', versions: ['>=4.4'] }, cassandra => {
|
|
48
|
+
addHook({ name: 'cassandra-driver', versions: ['>=4.4'], patchDefault: false }, (cassandra) => {
|
|
49
49
|
shimmer.wrap(cassandra.Client.prototype, '_execute', _execute => function (query, params, execOptions, callback) {
|
|
50
50
|
if (!startCh.hasSubscribers) {
|
|
51
51
|
return _execute.apply(this, arguments)
|
|
@@ -68,7 +68,7 @@ const isValid = (args) => {
|
|
|
68
68
|
return args.length === 4 || typeof args[3] === 'function'
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
addHook({ name: 'cassandra-driver', versions: ['3 - 4.3'] }, cassandra => {
|
|
71
|
+
addHook({ name: 'cassandra-driver', versions: ['3 - 4.3'], patchDefault: false }, (cassandra) => {
|
|
72
72
|
shimmer.wrap(cassandra.Client.prototype, '_innerExecute', _innerExecute =>
|
|
73
73
|
function (query, params, execOptions, callback) {
|
|
74
74
|
if (!startCh.hasSubscribers) {
|
|
@@ -102,11 +102,15 @@ function wrapNext (req, next) {
|
|
|
102
102
|
})
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
addHook({ name: 'connect', versions: ['>=3'] }, connect => {
|
|
105
|
+
addHook({ name: 'connect', versions: ['>=3.4.0'] }, (connect) => {
|
|
106
106
|
return shimmer.wrapFunction(connect, connect => wrapConnect(connect))
|
|
107
107
|
})
|
|
108
108
|
|
|
109
|
-
addHook({ name: 'connect', versions: ['
|
|
109
|
+
addHook({ name: 'connect', versions: ['>=3 <3.4.0'], file: 'lib/connect.js' }, (connect) => {
|
|
110
|
+
return shimmer.wrapFunction(connect, connect => wrapConnect(connect))
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
addHook({ name: 'connect', versions: ['2.2.2'], file: 'lib/connect.js' }, connect => {
|
|
110
114
|
shimmer.wrap(connect.proto, 'use', wrapUse)
|
|
111
115
|
shimmer.wrap(connect.proto, 'handle', wrapHandle)
|
|
112
116
|
|
|
@@ -82,10 +82,14 @@ let testManagementAttemptToFixRetries = 0
|
|
|
82
82
|
let testManagementTests = {}
|
|
83
83
|
let modifiedTests = {}
|
|
84
84
|
let numTestRetries = 0
|
|
85
|
-
let knownTests =
|
|
85
|
+
let knownTests = {}
|
|
86
86
|
let skippedSuites = []
|
|
87
87
|
let isSuitesSkipped = false
|
|
88
88
|
|
|
89
|
+
function isValidKnownTests (receivedKnownTests) {
|
|
90
|
+
return !!receivedKnownTests.cucumber
|
|
91
|
+
}
|
|
92
|
+
|
|
89
93
|
function getSuiteStatusFromTestStatuses (testStatuses) {
|
|
90
94
|
if (testStatuses.includes('fail')) {
|
|
91
95
|
return 'fail'
|
|
@@ -123,7 +127,10 @@ function getStatusFromResultLatest (result) {
|
|
|
123
127
|
}
|
|
124
128
|
|
|
125
129
|
function isNewTest (testSuite, testName) {
|
|
126
|
-
|
|
130
|
+
if (!isValidKnownTests(knownTests)) {
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
const testsForSuite = knownTests.cucumber[testSuite] || []
|
|
127
134
|
return !testsForSuite.includes(testName)
|
|
128
135
|
}
|
|
129
136
|
|
|
@@ -508,9 +515,9 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
508
515
|
pickleByFile = isCoordinator ? getPickleByFileNew(this) : getPickleByFile(this)
|
|
509
516
|
|
|
510
517
|
if (isKnownTestsEnabled) {
|
|
511
|
-
const isFaulty = getIsFaultyEarlyFlakeDetection(
|
|
518
|
+
const isFaulty = !isValidKnownTests(knownTests) || getIsFaultyEarlyFlakeDetection(
|
|
512
519
|
Object.keys(pickleByFile),
|
|
513
|
-
knownTests.cucumber
|
|
520
|
+
knownTests.cucumber,
|
|
514
521
|
earlyFlakeDetectionFaultyThreshold
|
|
515
522
|
)
|
|
516
523
|
if (isFaulty) {
|
|
@@ -592,6 +599,9 @@ function getWrappedStart (start, frameworkVersion, isParallel = false, isCoordin
|
|
|
592
599
|
// Handles EFD in both the main process and the worker process.
|
|
593
600
|
function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = false, isWorker = false) {
|
|
594
601
|
return async function () {
|
|
602
|
+
if (!testSuiteFinishCh.hasSubscribers) {
|
|
603
|
+
return runTestCaseFunction.apply(this, arguments)
|
|
604
|
+
}
|
|
595
605
|
const pickle = isNewerCucumberVersion
|
|
596
606
|
? arguments[0].pickle
|
|
597
607
|
: this.eventDataCollector.getPickle(arguments[0])
|
|
@@ -747,6 +757,9 @@ function getWrappedRunTestCase (runTestCaseFunction, isNewerCucumberVersion = fa
|
|
|
747
757
|
|
|
748
758
|
function getWrappedParseWorkerMessage (parseWorkerMessageFunction, isNewVersion) {
|
|
749
759
|
return function (worker, message) {
|
|
760
|
+
if (!testSuiteFinishCh.hasSubscribers) {
|
|
761
|
+
return parseWorkerMessageFunction.apply(this, arguments)
|
|
762
|
+
}
|
|
750
763
|
// If the message is an array, it's a dd-trace message, so we need to stop cucumber processing,
|
|
751
764
|
// or cucumber will throw an error
|
|
752
765
|
// TODO: identify the message better
|
|
@@ -972,10 +985,17 @@ addHook({
|
|
|
972
985
|
)
|
|
973
986
|
// EFD in parallel mode only supported in >=11.0.0
|
|
974
987
|
shimmer.wrap(adapterPackage.ChildProcessAdapter.prototype, 'startWorker', startWorker => function () {
|
|
975
|
-
if (isKnownTestsEnabled) {
|
|
988
|
+
if (isKnownTestsEnabled && isValidKnownTests(knownTests)) {
|
|
989
|
+
this.options.worldParameters._ddIsKnownTestsEnabled = true
|
|
976
990
|
this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled = isEarlyFlakeDetectionEnabled
|
|
977
991
|
this.options.worldParameters._ddKnownTests = knownTests
|
|
978
992
|
this.options.worldParameters._ddEarlyFlakeDetectionNumRetries = earlyFlakeDetectionNumRetries
|
|
993
|
+
} else {
|
|
994
|
+
isEarlyFlakeDetectionEnabled = false
|
|
995
|
+
isKnownTestsEnabled = false
|
|
996
|
+
this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled = false
|
|
997
|
+
this.options.worldParameters._ddIsKnownTestsEnabled = false
|
|
998
|
+
this.options.worldParameters._ddEarlyFlakeDetectionNumRetries = 0
|
|
979
999
|
}
|
|
980
1000
|
|
|
981
1001
|
if (isImpactedTestsEnabled) {
|
|
@@ -1001,9 +1021,14 @@ addHook({
|
|
|
1001
1021
|
'initialize',
|
|
1002
1022
|
initialize => async function () {
|
|
1003
1023
|
await initialize.apply(this, arguments)
|
|
1004
|
-
isKnownTestsEnabled = !!this.options.worldParameters.
|
|
1024
|
+
isKnownTestsEnabled = !!this.options.worldParameters._ddIsKnownTestsEnabled
|
|
1005
1025
|
if (isKnownTestsEnabled) {
|
|
1006
1026
|
knownTests = this.options.worldParameters._ddKnownTests
|
|
1027
|
+
// if for whatever reason the worker does not receive valid known tests, we disable EFD and known tests
|
|
1028
|
+
if (!isValidKnownTests(knownTests)) {
|
|
1029
|
+
isKnownTestsEnabled = false
|
|
1030
|
+
knownTests = {}
|
|
1031
|
+
}
|
|
1007
1032
|
}
|
|
1008
1033
|
isEarlyFlakeDetectionEnabled = !!this.options.worldParameters._ddIsEarlyFlakeDetectionEnabled
|
|
1009
1034
|
if (isEarlyFlakeDetectionEnabled) {
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { createWrapRouterMethod } = require('./router')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
|
-
const { addHook, channel } = require('./helpers/instrument')
|
|
6
|
-
const tracingChannel = require('dc-polyfill').tracingChannel
|
|
5
|
+
const { addHook, channel, tracingChannel } = require('./helpers/instrument')
|
|
7
6
|
|
|
8
7
|
const handleChannel = channel('apm:express:request:handle')
|
|
9
8
|
|
|
@@ -57,7 +56,7 @@ function wrapResponseRender (render) {
|
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
addHook({ name: 'express', versions: ['>=4'] }, express => {
|
|
59
|
+
addHook({ name: 'express', versions: ['>=4'], file: ['lib/express.js'] }, express => {
|
|
61
60
|
shimmer.wrap(express.application, 'handle', wrapHandle)
|
|
62
61
|
|
|
63
62
|
shimmer.wrap(express.response, 'json', wrapResponseJson)
|
|
@@ -70,7 +69,7 @@ addHook({ name: 'express', versions: ['>=4'] }, express => {
|
|
|
70
69
|
// Express 5 does not rely on router in the same way as v4 and should not be instrumented anymore.
|
|
71
70
|
// It would otherwise produce spans for router and express, and so duplicating them.
|
|
72
71
|
// We now fall back to router instrumentation
|
|
73
|
-
addHook({ name: 'express', versions: ['4'] }, express => {
|
|
72
|
+
addHook({ name: 'express', versions: ['4'], file: 'lib/express.js' }, express => {
|
|
74
73
|
shimmer.wrap(express.Router, 'use', wrapRouterMethod)
|
|
75
74
|
shimmer.wrap(express.Router, 'route', wrapRouterMethod)
|
|
76
75
|
|
|
@@ -132,12 +131,12 @@ function wrapProcessParamsMethod (requestPositionInArguments) {
|
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
133
|
|
|
135
|
-
addHook({ name: 'express', versions: ['>=4.0.0 <4.3.0'] }, express => {
|
|
134
|
+
addHook({ name: 'express', versions: ['>=4.0.0 <4.3.0'], file: ['lib/express.js'] }, express => {
|
|
136
135
|
shimmer.wrap(express.Router, 'process_params', wrapProcessParamsMethod(1))
|
|
137
136
|
return express
|
|
138
137
|
})
|
|
139
138
|
|
|
140
|
-
addHook({ name: 'express', versions: ['>=4.3.0 <5.0.0'] }, express => {
|
|
139
|
+
addHook({ name: 'express', versions: ['>=4.3.0 <5.0.0'], file: ['lib/express.js'] }, express => {
|
|
141
140
|
shimmer.wrap(express.Router, 'process_params', wrapProcessParamsMethod(2))
|
|
142
141
|
return express
|
|
143
142
|
})
|
|
@@ -265,7 +265,7 @@ function canPublishResponsePayload (payload) {
|
|
|
265
265
|
!ArrayBuffer.isView(payload) // TypedArray
|
|
266
266
|
}
|
|
267
267
|
|
|
268
|
-
addHook({ name: 'fastify', versions: ['>=3'] }, fastify => {
|
|
268
|
+
addHook({ name: 'fastify', versions: ['>=3'] }, (fastify) => {
|
|
269
269
|
const wrapped = shimmer.wrapFunction(fastify, fastify => wrapFastify(fastify, true))
|
|
270
270
|
|
|
271
271
|
wrapped.fastify = wrapped
|
|
@@ -274,11 +274,11 @@ addHook({ name: 'fastify', versions: ['>=3'] }, fastify => {
|
|
|
274
274
|
return wrapped
|
|
275
275
|
})
|
|
276
276
|
|
|
277
|
-
addHook({ name: 'fastify', versions: ['2'] }, fastify => {
|
|
277
|
+
addHook({ name: 'fastify', versions: ['2'] }, (fastify) => {
|
|
278
278
|
return shimmer.wrapFunction(fastify, fastify => wrapFastify(fastify, true))
|
|
279
279
|
})
|
|
280
280
|
|
|
281
|
-
addHook({ name: 'fastify', versions: ['1'] }, fastify => {
|
|
281
|
+
addHook({ name: 'fastify', versions: ['1'] }, (fastify) => {
|
|
282
282
|
return shimmer.wrapFunction(fastify, fastify => wrapFastify(fastify, false))
|
|
283
283
|
})
|
|
284
284
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
|
|
3
|
-
const path = require('path')
|
|
4
2
|
const iitm = require('../../../dd-trace/src/iitm')
|
|
3
|
+
const path = require('path')
|
|
5
4
|
const ritm = require('../../../dd-trace/src/ritm')
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -20,29 +19,43 @@ function Hook (modules, hookOptions, onrequire) {
|
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
this._patched = Object.create(null)
|
|
22
|
+
const patched = new WeakMap()
|
|
23
23
|
|
|
24
|
-
const safeHook = (moduleExports, moduleName, moduleBaseDir, moduleVersion) => {
|
|
24
|
+
const safeHook = (moduleExports, moduleName, moduleBaseDir, moduleVersion, isIitm) => {
|
|
25
25
|
const parts = [moduleBaseDir, moduleName].filter(Boolean)
|
|
26
26
|
const filename = path.join(...parts)
|
|
27
27
|
|
|
28
|
-
if (this._patched[filename]
|
|
28
|
+
if (this._patched[filename] && patched.has(moduleExports)) {
|
|
29
|
+
return patched.get(moduleExports)
|
|
30
|
+
}
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
let defaultWrapResult
|
|
33
|
+
|
|
34
|
+
if (
|
|
35
|
+
isIitm &&
|
|
36
|
+
moduleExports.default &&
|
|
37
|
+
(typeof moduleExports.default === 'object' ||
|
|
38
|
+
typeof moduleExports.default === 'function')
|
|
39
|
+
) {
|
|
40
|
+
defaultWrapResult = onrequire(moduleExports.default, moduleName, moduleBaseDir, moduleVersion, isIitm)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const newExports = onrequire(moduleExports, moduleName, moduleBaseDir, moduleVersion, isIitm)
|
|
44
|
+
|
|
45
|
+
if (defaultWrapResult) newExports.default = defaultWrapResult
|
|
31
46
|
|
|
32
|
-
|
|
47
|
+
this._patched[filename] = true
|
|
48
|
+
if (newExports &&
|
|
49
|
+
(typeof newExports === 'object' ||
|
|
50
|
+
typeof newExports === 'function')) {
|
|
51
|
+
patched.set(moduleExports, newExports)
|
|
52
|
+
}
|
|
53
|
+
return newExports
|
|
33
54
|
}
|
|
34
55
|
|
|
35
56
|
this._ritmHook = ritm(modules, {}, safeHook)
|
|
36
57
|
this._iitmHook = iitm(modules, hookOptions, (moduleExports, moduleName, moduleBaseDir) => {
|
|
37
|
-
|
|
38
|
-
// modules and not ESM. In the meantime, all the modules we instrument are
|
|
39
|
-
// CommonJS modules for which the default export is always moved to
|
|
40
|
-
// `default` anyway.
|
|
41
|
-
if (moduleExports && moduleExports.default) {
|
|
42
|
-
moduleExports.default = safeHook(moduleExports.default, moduleName, moduleBaseDir)
|
|
43
|
-
return moduleExports
|
|
44
|
-
}
|
|
45
|
-
return safeHook(moduleExports, moduleName, moduleBaseDir)
|
|
58
|
+
return safeHook(moduleExports, moduleName, moduleBaseDir, null, true)
|
|
46
59
|
})
|
|
47
60
|
}
|
|
48
61
|
|
|
@@ -16,6 +16,7 @@ module.exports = {
|
|
|
16
16
|
'@graphql-tools/executor': () => require('../graphql'),
|
|
17
17
|
'@grpc/grpc-js': () => require('../grpc'),
|
|
18
18
|
'@hapi/hapi': () => require('../hapi'),
|
|
19
|
+
'@happy-dom/jest-environment': () => require('../jest'),
|
|
19
20
|
'@jest/core': () => require('../jest'),
|
|
20
21
|
'@jest/reporters': () => require('../jest'),
|
|
21
22
|
'@jest/test-sequencer': () => require('../jest'),
|
|
@@ -130,6 +131,7 @@ module.exports = {
|
|
|
130
131
|
sequelize: () => require('../sequelize'),
|
|
131
132
|
sharedb: () => require('../sharedb'),
|
|
132
133
|
tedious: () => require('../tedious'),
|
|
134
|
+
tinypool: { esmFirst: true, fn: () => require('../vitest') },
|
|
133
135
|
undici: () => require('../undici'),
|
|
134
136
|
url: () => require('../url'),
|
|
135
137
|
vitest: { esmFirst: true, fn: () => require('../vitest') },
|