dd-trace 5.96.0 → 5.97.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +34 -0
- package/package.json +9 -7
- package/packages/datadog-esbuild/index.js +20 -9
- package/packages/datadog-instrumentations/src/child_process.js +7 -17
- package/packages/datadog-instrumentations/src/crypto.js +1 -2
- package/packages/datadog-instrumentations/src/cucumber.js +4 -1
- package/packages/datadog-instrumentations/src/cypress-config.js +324 -0
- package/packages/datadog-instrumentations/src/cypress.js +86 -4
- package/packages/datadog-instrumentations/src/dns.js +1 -2
- package/packages/datadog-instrumentations/src/express.js +4 -4
- package/packages/datadog-instrumentations/src/fs.js +27 -29
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
- package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
- package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
- package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
- package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
- package/packages/datadog-instrumentations/src/http/client.js +2 -3
- package/packages/datadog-instrumentations/src/http/server.js +2 -5
- package/packages/datadog-instrumentations/src/http2/client.js +1 -3
- package/packages/datadog-instrumentations/src/http2/server.js +1 -3
- package/packages/datadog-instrumentations/src/jest.js +13 -4
- package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
- package/packages/datadog-instrumentations/src/mocha/utils.js +4 -1
- package/packages/datadog-instrumentations/src/net.js +2 -8
- package/packages/datadog-instrumentations/src/pino.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +4 -1
- package/packages/datadog-instrumentations/src/prisma.js +1 -2
- package/packages/datadog-instrumentations/src/selenium.js +4 -1
- package/packages/datadog-instrumentations/src/sequelize.js +1 -1
- package/packages/datadog-instrumentations/src/url.js +1 -3
- package/packages/datadog-instrumentations/src/vitest.js +5 -1
- package/packages/datadog-instrumentations/src/vm.js +1 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +4 -3
- package/packages/datadog-plugin-cucumber/src/index.js +7 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +57 -5
- package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +4 -2
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-next/src/index.js +2 -14
- package/packages/datadog-plugin-openai/src/services.js +1 -0
- package/packages/datadog-webpack/index.js +3 -3
- package/packages/dd-trace/index.js +12 -10
- package/packages/dd-trace/src/agent/url.js +2 -2
- package/packages/dd-trace/src/aiguard/sdk.js +4 -0
- package/packages/dd-trace/src/appsec/blocking.js +3 -0
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
- package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
- package/packages/dd-trace/src/config/defaults.js +316 -146
- package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
- package/packages/dd-trace/src/config/helper.js +59 -10
- package/packages/dd-trace/src/config/index.js +569 -1505
- package/packages/dd-trace/src/config/parsers.js +256 -0
- package/packages/dd-trace/src/config/remote_config.js +59 -2
- package/packages/dd-trace/src/config/supported-configurations.json +350 -433
- package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
- package/packages/dd-trace/src/crashtracking/index.js +1 -7
- package/packages/dd-trace/src/debugger/index.js +1 -1
- package/packages/dd-trace/src/dogstatsd.js +12 -9
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
- package/packages/dd-trace/src/exporters/common/request.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +12 -2
- package/packages/dd-trace/src/heap_snapshots.js +3 -0
- package/packages/dd-trace/src/index.js +5 -2
- package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
- package/packages/dd-trace/src/llmobs/index.js +4 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
- package/packages/dd-trace/src/llmobs/sdk.js +12 -8
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/tagger.js +9 -6
- package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
- package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
- package/packages/dd-trace/src/log/index.js +26 -55
- package/packages/dd-trace/src/log/writer.js +7 -19
- package/packages/dd-trace/src/noop/proxy.js +8 -0
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
- package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
- package/packages/dd-trace/src/plugin_manager.js +8 -6
- package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
- package/packages/dd-trace/src/plugins/plugin.js +7 -4
- package/packages/dd-trace/src/process-tags/index.js +3 -0
- package/packages/dd-trace/src/profiler.js +27 -2
- package/packages/dd-trace/src/profiling/config.js +73 -241
- package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
- package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
- package/packages/dd-trace/src/profiling/profiler.js +56 -44
- package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
- package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
- package/packages/dd-trace/src/propagation-hash/index.js +2 -1
- package/packages/dd-trace/src/proxy.js +32 -3
- package/packages/dd-trace/src/remote_config/index.js +3 -0
- package/packages/dd-trace/src/require-package-json.js +8 -4
- package/packages/dd-trace/src/ritm.js +58 -26
- package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -0
- package/packages/dd-trace/src/sampler.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -0
- package/packages/dd-trace/src/telemetry/index.js +2 -3
- package/packages/dd-trace/src/telemetry/send-data.js +5 -19
- package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
- package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
- package/packages/dd-trace/src/util.js +0 -9
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { builtinModules } = require('module')
|
|
3
4
|
const path = require('path')
|
|
4
5
|
const { channel } = require('dc-polyfill')
|
|
5
6
|
const satisfies = require('../../../../vendor/dist/semifies')
|
|
6
|
-
const requirePackageJson = require('../../../dd-trace/src/require-package-json')
|
|
7
7
|
const log = require('../../../dd-trace/src/log')
|
|
8
8
|
const telemetry = require('../../../dd-trace/src/guardrails/telemetry')
|
|
9
9
|
const { IS_SERVERLESS } = require('../../../dd-trace/src/serverless')
|
|
@@ -36,27 +36,47 @@ if (!disabledInstrumentations.has('process')) {
|
|
|
36
36
|
require('../process')
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
const HOOK_SYMBOL = Symbol('hookExportsSet')
|
|
40
|
-
|
|
41
39
|
if (DD_TRACE_DEBUG && DD_TRACE_DEBUG.toLowerCase() !== 'false') {
|
|
42
40
|
checkRequireCache.checkForRequiredModules()
|
|
43
41
|
setImmediate(checkRequireCache.checkForPotentialConflicts)
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
const seenCombo = new Set()
|
|
47
|
-
const allInstrumentations = {}
|
|
48
|
-
|
|
49
44
|
for (const inst of disabledInstrumentations) {
|
|
50
45
|
rewriter.disable(inst)
|
|
51
46
|
}
|
|
52
47
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
/** @type {Map<string, object>} */
|
|
49
|
+
const instrumentedNodeModules = new Map()
|
|
50
|
+
/** @type {Map<string, boolean>} */
|
|
51
|
+
const instrumentedIntegrationsSuccess = new Map()
|
|
52
|
+
/** @type {Set<string>} */
|
|
53
|
+
const alreadyLoggedIncompatibleIntegrations = new Set()
|
|
54
|
+
|
|
55
|
+
// Always disable prefixed and unprefixed node modules if one is disabled.
|
|
56
|
+
if (disabledInstrumentations.size) {
|
|
57
|
+
const builtinsSet = new Set(builtinModules)
|
|
58
|
+
for (const name of disabledInstrumentations) {
|
|
59
|
+
const hasPrefix = name.startsWith('node:')
|
|
60
|
+
if (hasPrefix || builtinsSet.has(name)) {
|
|
61
|
+
if (hasPrefix) {
|
|
62
|
+
const unprefixedName = name.slice(5)
|
|
63
|
+
if (!disabledInstrumentations.has(unprefixedName)) {
|
|
64
|
+
disabledInstrumentations.add(unprefixedName)
|
|
65
|
+
}
|
|
66
|
+
} else if (!disabledInstrumentations.has(`node:${name}`)) {
|
|
67
|
+
disabledInstrumentations.add(`node:${name}`)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
builtinsSet.clear()
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const name of names) {
|
|
75
|
+
if (disabledInstrumentations.has(name)) continue
|
|
56
76
|
|
|
57
77
|
const hookOptions = {}
|
|
58
78
|
|
|
59
|
-
let hook = hooks[
|
|
79
|
+
let hook = hooks[name]
|
|
60
80
|
|
|
61
81
|
if (hook !== null && typeof hook === 'object') {
|
|
62
82
|
if (hook.serverless === false && IS_SERVERLESS) continue
|
|
@@ -65,173 +85,114 @@ for (const packageName of names) {
|
|
|
65
85
|
hook = hook.fn
|
|
66
86
|
}
|
|
67
87
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
88
|
+
Hook([name], hookOptions, (moduleExports, moduleName, moduleBaseDir, moduleVersion, isIitm) => {
|
|
89
|
+
// All loaded versions are first expected to fail instrumentation.
|
|
90
|
+
if (!instrumentedIntegrationsSuccess.has(`${name}@${moduleVersion}`)) {
|
|
91
|
+
instrumentedIntegrationsSuccess.set(`${name}@${moduleVersion}`, false)
|
|
92
|
+
}
|
|
73
93
|
|
|
74
94
|
// This executes the integration file thus adding its entries to `instrumentations`
|
|
75
95
|
hook()
|
|
76
96
|
|
|
77
|
-
if (!instrumentations[
|
|
97
|
+
if (!instrumentations[name] || moduleExports === instrumentedNodeModules.get(name)) {
|
|
78
98
|
return moduleExports
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
101
|
+
// Used for node: prefixed modules to prevent double instrumentation.
|
|
102
|
+
if (moduleBaseDir) {
|
|
103
|
+
moduleName = moduleName.replace(pathSepExpr, '/')
|
|
104
|
+
} else {
|
|
105
|
+
instrumentedNodeModules.set(name, moduleExports)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
for (const { file, versions, hook, filePattern, patchDefault } of instrumentations[name]) {
|
|
109
|
+
if (isIitm && patchDefault === !!moduleExports.default) {
|
|
110
|
+
if (patchDefault) {
|
|
111
|
+
moduleExports = moduleExports.default
|
|
112
|
+
} else {
|
|
113
|
+
return moduleExports
|
|
114
|
+
}
|
|
87
115
|
}
|
|
88
116
|
|
|
89
|
-
let fullFilePattern = filePattern
|
|
90
117
|
const fullFilename = filename(name, file)
|
|
91
|
-
if (fullFilePattern) {
|
|
92
|
-
fullFilePattern = filename(name, fullFilePattern)
|
|
93
|
-
}
|
|
94
118
|
|
|
95
|
-
// Create a WeakSet associated with the hook function so that patches on the same moduleExport only happens once
|
|
96
|
-
// for example by instrumenting both dns and node:dns double the spans would be created
|
|
97
|
-
// since they both patch the same moduleExport, this WeakSet is used to mitigate that
|
|
98
|
-
// TODO(BridgeAR): Instead of using a WeakSet here, why not just use aliases for the hook in register?
|
|
99
|
-
// That way it would also not be duplicated. The actual name being used has to be identified else wise.
|
|
100
|
-
// Maybe it is also not important to know what name was actually used?
|
|
101
|
-
hook[HOOK_SYMBOL] ??= new WeakSet()
|
|
102
119
|
let matchesFile = moduleName === fullFilename
|
|
103
120
|
|
|
104
121
|
if (!matchesFile && isRelativeRequire(name)) matchesFile = true
|
|
105
122
|
|
|
123
|
+
const fullFilePattern = filePattern && filename(name, filePattern)
|
|
106
124
|
if (fullFilePattern) {
|
|
107
125
|
// Some libraries include a hash in their filenames when installed,
|
|
108
126
|
// so our instrumentation has to include a '.*' to match them for more than a single version.
|
|
109
|
-
matchesFile
|
|
127
|
+
matchesFile ||= new RegExp(fullFilePattern).test(moduleName)
|
|
110
128
|
}
|
|
111
129
|
|
|
112
|
-
if (matchesFile) {
|
|
113
|
-
|
|
130
|
+
if (matchesFile && matchVersion(moduleVersion, versions)) {
|
|
131
|
+
// Do not log in case of an error to prevent duplicate telemetry for the same integration version.
|
|
132
|
+
instrumentedIntegrationsSuccess.set(`${name}@${moduleVersion}`, true)
|
|
114
133
|
try {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
namesAndSuccesses[`${name}@${version}`] = false
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (matchVersion(version, versions)) {
|
|
133
|
-
allInstrumentations[instrumentationFileName] = true
|
|
134
|
-
|
|
135
|
-
// Check if the hook already has a set moduleExport
|
|
136
|
-
if (hook[HOOK_SYMBOL].has(moduleExports)) {
|
|
137
|
-
namesAndSuccesses[`${name}@${version}`] = true
|
|
138
|
-
return moduleExports
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
loadChannel.publish({ name, version, file })
|
|
143
|
-
// Send the name and version of the module back to the callback because now addHook
|
|
144
|
-
// takes in an array of names so by passing the name the callback will know which module name is being used
|
|
145
|
-
// TODO(BridgeAR): This is only true in case the name is identical
|
|
146
|
-
// in all loads. If they deviate, the deviating name would not be
|
|
147
|
-
// picked up due to the unification. Check what modules actually use the name.
|
|
148
|
-
// TODO(BridgeAR): Only replace moduleExports if the hook returns a new value.
|
|
149
|
-
// This allows to reduce the instrumentation code (no return needed).
|
|
150
|
-
|
|
151
|
-
moduleExports = hook(moduleExports, version, name, isIitm) ?? moduleExports
|
|
152
|
-
// Set the moduleExports in the hooks WeakSet
|
|
153
|
-
hook[HOOK_SYMBOL].add(moduleExports)
|
|
154
|
-
} catch (e) {
|
|
155
|
-
log.info('Error during ddtrace instrumentation of application, aborting.', e)
|
|
156
|
-
telemetry('error', [
|
|
157
|
-
`error_type:${e.constructor.name}`,
|
|
158
|
-
`integration:${name}`,
|
|
159
|
-
`integration_version:${version}`,
|
|
160
|
-
], {
|
|
161
|
-
result: 'error',
|
|
162
|
-
result_class: 'internal_error',
|
|
163
|
-
result_reason: `Error during instrumentation of ${name}@${version}: ${e.message}`,
|
|
164
|
-
})
|
|
165
|
-
}
|
|
166
|
-
namesAndSuccesses[`${name}@${version}`] = true
|
|
134
|
+
loadChannel.publish({ name })
|
|
135
|
+
|
|
136
|
+
moduleExports = hook(moduleExports, moduleVersion, isIitm) ?? moduleExports
|
|
137
|
+
} catch (error) {
|
|
138
|
+
log.info('Error during ddtrace instrumentation of application, aborting.', error)
|
|
139
|
+
telemetry('error', [
|
|
140
|
+
`error_type:${error.constructor.name}`,
|
|
141
|
+
`integration:${name}`,
|
|
142
|
+
`integration_version:${moduleVersion}`,
|
|
143
|
+
], {
|
|
144
|
+
result: 'error',
|
|
145
|
+
result_class: 'internal_error',
|
|
146
|
+
result_reason: `Error during instrumentation of ${name}@${moduleVersion}: ${error.message}`,
|
|
147
|
+
})
|
|
167
148
|
}
|
|
168
149
|
}
|
|
169
150
|
}
|
|
170
|
-
for (const nameVersion of Object.keys(namesAndSuccesses)) {
|
|
171
|
-
const [name, version] = nameVersion.split('@')
|
|
172
|
-
const success = namesAndSuccesses[nameVersion]
|
|
173
|
-
// we check allVersions to see if any version of the integration was successfully instrumented
|
|
174
|
-
if (!success && !seenCombo.has(nameVersion) && !allInstrumentations[instrumentationFileName]) {
|
|
175
|
-
telemetry('abort.integration', [
|
|
176
|
-
`integration:${name}`,
|
|
177
|
-
`integration_version:${version}`,
|
|
178
|
-
], {
|
|
179
|
-
result: 'abort',
|
|
180
|
-
result_class: 'incompatible_library',
|
|
181
|
-
result_reason: `Incompatible integration version: ${name}@${version}`,
|
|
182
|
-
})
|
|
183
|
-
log.info('Found incompatible integration version: %s', nameVersion)
|
|
184
|
-
seenCombo.add(nameVersion)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
151
|
|
|
188
152
|
return moduleExports
|
|
189
153
|
})
|
|
190
154
|
}
|
|
191
155
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
156
|
+
globalThis[Symbol.for('dd-trace')]?.beforeExitHandlers.add(logAbortedIntegrations)
|
|
157
|
+
// TODO: check if we want to stop using channels for single subscriber tasks
|
|
158
|
+
channel('dd-trace:exporter:first-flush').subscribe(logAbortedIntegrations)
|
|
195
159
|
|
|
196
|
-
function
|
|
197
|
-
|
|
198
|
-
|
|
160
|
+
function logAbortedIntegrations () {
|
|
161
|
+
for (const [nameVersion, success] of instrumentedIntegrationsSuccess) {
|
|
162
|
+
// Only ever log a single version of an integration, even if it is loaded later.
|
|
163
|
+
if (!success && !alreadyLoggedIncompatibleIntegrations.has(nameVersion)) {
|
|
164
|
+
const [name, version] = nameVersion.split('@')
|
|
165
|
+
telemetry('abort.integration', [
|
|
166
|
+
`integration:${name}`,
|
|
167
|
+
`integration_version:${version}`,
|
|
168
|
+
], {
|
|
169
|
+
result: 'abort',
|
|
170
|
+
result_class: 'incompatible_library',
|
|
171
|
+
result_reason: `Incompatible integration version: ${name}@${version}`,
|
|
172
|
+
})
|
|
173
|
+
log.info('Found incompatible integration version: %s', nameVersion)
|
|
174
|
+
alreadyLoggedIncompatibleIntegrations.add(nameVersion)
|
|
175
|
+
}
|
|
199
176
|
}
|
|
177
|
+
// Clear the map to avoid reporting the same integration version again.
|
|
178
|
+
instrumentedIntegrationsSuccess.clear()
|
|
200
179
|
}
|
|
201
180
|
|
|
202
|
-
|
|
203
|
-
|
|
181
|
+
/**
|
|
182
|
+
* @param {string|undefined} version
|
|
183
|
+
* @param {string[]|undefined} ranges
|
|
184
|
+
*/
|
|
185
|
+
function matchVersion (version, ranges) {
|
|
186
|
+
return !version || !ranges || ranges.some(range => satisfies(version, range))
|
|
204
187
|
}
|
|
205
188
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
// @redis/client -> "() => require('../redis')" -> redis
|
|
214
|
-
//
|
|
215
|
-
function parseHookInstrumentationFileName (packageName) {
|
|
216
|
-
let hook = hooks[packageName]
|
|
217
|
-
if (hook.fn) {
|
|
218
|
-
hook = hook.fn
|
|
219
|
-
}
|
|
220
|
-
const hookString = hook.toString()
|
|
221
|
-
const regex = /require\('([^']*)'\)/
|
|
222
|
-
const match = hookString.match(regex)
|
|
223
|
-
|
|
224
|
-
// try to capture the hook require file location.
|
|
225
|
-
if (match && match[1]) {
|
|
226
|
-
let moduleName = match[1]
|
|
227
|
-
// Remove leading '../' if present
|
|
228
|
-
if (moduleName.startsWith('../')) {
|
|
229
|
-
moduleName = moduleName.slice(3)
|
|
230
|
-
}
|
|
231
|
-
return moduleName
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return null
|
|
189
|
+
/**
|
|
190
|
+
* @param {string} name
|
|
191
|
+
* @param {string} [file]
|
|
192
|
+
* @returns {string}
|
|
193
|
+
*/
|
|
194
|
+
function filename (name, file) {
|
|
195
|
+
return file ? `${name}/${file}` : name
|
|
235
196
|
}
|
|
236
197
|
|
|
237
198
|
module.exports = {
|
|
@@ -16,9 +16,8 @@ const asyncStartChannel = channel('apm:http:client:request:asyncStart')
|
|
|
16
16
|
const errorChannel = channel('apm:http:client:request:error')
|
|
17
17
|
const responseFinishChannel = channel('apm:http:client:response:finish')
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
addHook({ name: names }, hookFn)
|
|
19
|
+
addHook({ name: 'http' }, hookFn)
|
|
20
|
+
addHook({ name: 'https' }, hookFn)
|
|
22
21
|
|
|
23
22
|
function hookFn (http) {
|
|
24
23
|
patch(http, 'request')
|
|
@@ -16,10 +16,7 @@ const startSetHeaderCh = channel('datadog:http:server:response:set-header:start'
|
|
|
16
16
|
|
|
17
17
|
const requestFinishedSet = new WeakSet()
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
const httpsNames = ['https', 'node:https']
|
|
21
|
-
|
|
22
|
-
addHook({ name: httpNames }, http => {
|
|
19
|
+
addHook({ name: 'http' }, http => {
|
|
23
20
|
shimmer.wrap(http.ServerResponse.prototype, 'emit', wrapResponseEmit)
|
|
24
21
|
shimmer.wrap(http.Server.prototype, 'emit', wrapEmit)
|
|
25
22
|
shimmer.wrap(http.ServerResponse.prototype, 'writeHead', wrapWriteHead)
|
|
@@ -34,7 +31,7 @@ addHook({ name: httpNames }, http => {
|
|
|
34
31
|
return http
|
|
35
32
|
})
|
|
36
33
|
|
|
37
|
-
addHook({ name:
|
|
34
|
+
addHook({ name: 'https' }, http => {
|
|
38
35
|
// http.ServerResponse not present on https
|
|
39
36
|
shimmer.wrap(http.Server.prototype, 'emit', wrapEmit)
|
|
40
37
|
return http
|
|
@@ -10,8 +10,6 @@ const asyncStartChannel = channel('apm:http2:client:request:asyncStart')
|
|
|
10
10
|
const asyncEndChannel = channel('apm:http2:client:request:asyncEnd')
|
|
11
11
|
const errorChannel = channel('apm:http2:client:request:error')
|
|
12
12
|
|
|
13
|
-
const names = ['http2', 'node:http2']
|
|
14
|
-
|
|
15
13
|
function createWrapEmit (ctx) {
|
|
16
14
|
return function wrapEmit (emit) {
|
|
17
15
|
return function (event, arg1) {
|
|
@@ -68,7 +66,7 @@ function wrapConnect (connect) {
|
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
addHook({ name:
|
|
69
|
+
addHook({ name: 'http2' }, http2 => {
|
|
72
70
|
shimmer.wrap(http2, 'connect', wrapConnect)
|
|
73
71
|
if (http2.default) http2.default.connect = http2.connect
|
|
74
72
|
|
|
@@ -13,9 +13,7 @@ const startServerCh = channel('apm:http2:server:request:start')
|
|
|
13
13
|
const errorServerCh = channel('apm:http2:server:request:error')
|
|
14
14
|
const emitCh = channel('apm:http2:server:response:emit')
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
addHook({ name: names }, http2 => {
|
|
16
|
+
addHook({ name: 'http2' }, http2 => {
|
|
19
17
|
shimmer.wrap(http2, 'createSecureServer', wrapCreateServer)
|
|
20
18
|
shimmer.wrap(http2, 'createServer', wrapCreateServer)
|
|
21
19
|
})
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real timers at module load time, before any test can install fake timers.
|
|
4
|
+
const realSetTimeout = setTimeout
|
|
5
|
+
|
|
3
6
|
const path = require('path')
|
|
4
7
|
const shimmer = require('../../datadog-shimmer')
|
|
5
8
|
const log = require('../../dd-trace/src/log')
|
|
@@ -111,6 +114,8 @@ const efdDeterminedRetries = new Map()
|
|
|
111
114
|
const efdSlowAbortedTests = new Set()
|
|
112
115
|
// Tests added as EFD new-test candidates (not ATF, not impacted).
|
|
113
116
|
const efdNewTestCandidates = new Set()
|
|
117
|
+
// Tests that are genuinely new (not in known tests list).
|
|
118
|
+
const newTests = new Set()
|
|
114
119
|
const testSuiteAbsolutePathsWithFastCheck = new Set()
|
|
115
120
|
const testSuiteJestObjects = new Map()
|
|
116
121
|
|
|
@@ -485,7 +490,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
485
490
|
}
|
|
486
491
|
|
|
487
492
|
if (this.isKnownTestsEnabled) {
|
|
488
|
-
isNewTest =
|
|
493
|
+
isNewTest = newTests.has(testName)
|
|
489
494
|
}
|
|
490
495
|
|
|
491
496
|
const willRunEfd = this.isEarlyFlakeDetectionEnabled && (isNewTest || isModified)
|
|
@@ -605,6 +610,9 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
605
610
|
}
|
|
606
611
|
if (!isAttemptToFix && this.isKnownTestsEnabled) {
|
|
607
612
|
const isNew = !this.knownTestsForThisSuite.includes(testFullName)
|
|
613
|
+
if (isNew && !isSkipped) {
|
|
614
|
+
newTests.add(testFullName)
|
|
615
|
+
}
|
|
608
616
|
if (isNew && !isSkipped && !retriedTestsToNumAttempts.has(testFullName)) {
|
|
609
617
|
if (DYNAMIC_NAME_RE.test(testFullName)) {
|
|
610
618
|
// Populated directly for runInBand; for parallel workers the main process
|
|
@@ -715,7 +723,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
715
723
|
let isEfdRetry = false
|
|
716
724
|
// We'll store the test statuses of the retries
|
|
717
725
|
if (this.isKnownTestsEnabled) {
|
|
718
|
-
const isNewTest =
|
|
726
|
+
const isNewTest = newTests.has(testName)
|
|
719
727
|
if (isNewTest) {
|
|
720
728
|
if (newTestsTestStatuses.has(testName)) {
|
|
721
729
|
newTestsTestStatuses.get(testName).push(status)
|
|
@@ -776,7 +784,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
776
784
|
// This means that tests retried with DI are BREAKPOINT_HIT_GRACE_PERIOD_MS slower at least.
|
|
777
785
|
if (status === 'fail' && mightHitBreakpoint) {
|
|
778
786
|
await new Promise(resolve => {
|
|
779
|
-
|
|
787
|
+
realSetTimeout(() => {
|
|
780
788
|
resolve()
|
|
781
789
|
}, BREAKPOINT_HIT_GRACE_PERIOD_MS)
|
|
782
790
|
})
|
|
@@ -811,6 +819,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
811
819
|
efdDeterminedRetries.clear()
|
|
812
820
|
efdSlowAbortedTests.clear()
|
|
813
821
|
efdNewTestCandidates.clear()
|
|
822
|
+
newTests.clear()
|
|
814
823
|
retriedTestsToNumAttempts.clear()
|
|
815
824
|
attemptToFixRetriedTestsStatuses.clear()
|
|
816
825
|
testsToBeRetried.clear()
|
|
@@ -1345,7 +1354,7 @@ function getCliWrapper (isNewJestVersion) {
|
|
|
1345
1354
|
})
|
|
1346
1355
|
|
|
1347
1356
|
const timeoutPromise = new Promise((resolve) => {
|
|
1348
|
-
timeoutId =
|
|
1357
|
+
timeoutId = realSetTimeout(() => {
|
|
1349
1358
|
resolve('timeout')
|
|
1350
1359
|
}, FLUSH_TIMEOUT).unref()
|
|
1351
1360
|
})
|
|
@@ -14,7 +14,7 @@ function wrapRequest (original) {
|
|
|
14
14
|
addHook({
|
|
15
15
|
name: 'limitd-client',
|
|
16
16
|
versions: ['>=2.8'],
|
|
17
|
-
file:
|
|
17
|
+
file: 'client.js',
|
|
18
18
|
}, LimitdClient => {
|
|
19
19
|
shimmer.wrap(LimitdClient.prototype, '_directRequest', wrapRequest)
|
|
20
20
|
shimmer.wrap(LimitdClient.prototype, '_retriedRequest', wrapRequest)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real timers at module load time, before any test can install fake timers.
|
|
4
|
+
const realSetTimeout = setTimeout
|
|
5
|
+
|
|
3
6
|
const { getTestSuitePath, DYNAMIC_NAME_RE } = require('../../../dd-trace/src/plugins/util/test')
|
|
4
7
|
const { channel } = require('../helpers/instrument')
|
|
5
8
|
const shimmer = require('../../../datadog-shimmer')
|
|
@@ -293,7 +296,7 @@ function getOnTestEndHandler (config) {
|
|
|
293
296
|
// This means that tests retried with DI are BREAKPOINT_HIT_GRACE_PERIOD_MS slower at least.
|
|
294
297
|
if (test._ddShouldWaitForHitProbe || test._retriedTest?._ddShouldWaitForHitProbe) {
|
|
295
298
|
await new Promise((resolve) => {
|
|
296
|
-
|
|
299
|
+
realSetTimeout(() => {
|
|
297
300
|
resolve()
|
|
298
301
|
}, BREAKPOINT_HIT_GRACE_PERIOD_MS)
|
|
299
302
|
})
|
|
@@ -16,16 +16,10 @@ const errorTCPCh = channel('apm:net:tcp:error')
|
|
|
16
16
|
const readyCh = channel('apm:net:tcp:ready')
|
|
17
17
|
const connectionCh = channel('apm:net:tcp:connection')
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
addHook({ name: names }, (net, version, name) => {
|
|
19
|
+
addHook({ name: 'net' }, (net) => {
|
|
22
20
|
// explicitly require dns so that net gets an instrumented instance
|
|
23
21
|
// so that we don't miss the dns calls
|
|
24
|
-
|
|
25
|
-
require('dns')
|
|
26
|
-
} else {
|
|
27
|
-
require('node:dns')
|
|
28
|
-
}
|
|
22
|
+
require('node:dns')
|
|
29
23
|
|
|
30
24
|
shimmer.wrap(net.Socket.prototype, 'connect', connect => function () {
|
|
31
25
|
if (!startICPCh.hasSubscribers || !startTCPCh.hasSubscribers) {
|
|
@@ -97,7 +97,7 @@ addHook({ name: 'pino', versions: ['>=5.14.0 <6.8.0'] }, (pino) => {
|
|
|
97
97
|
return wrapped
|
|
98
98
|
})
|
|
99
99
|
|
|
100
|
-
addHook({ name: 'pino', versions: ['>=6.8.0'], patchDefault: false }, (pino
|
|
100
|
+
addHook({ name: 'pino', versions: ['>=6.8.0'], patchDefault: false }, (pino) => {
|
|
101
101
|
const mixinSym = pino.symbols.mixinSym
|
|
102
102
|
|
|
103
103
|
const wrapped = shimmer.wrapFunction(pino, pino => wrapPino(mixinSym, wrapMixin, pino))
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real timers at module load time, before any test can install fake timers.
|
|
4
|
+
const realSetTimeout = setTimeout
|
|
5
|
+
|
|
3
6
|
const satisfies = require('../../../vendor/dist/semifies')
|
|
4
7
|
|
|
5
8
|
const shimmer = require('../../datadog-shimmer')
|
|
@@ -1216,7 +1219,7 @@ addHook({
|
|
|
1216
1219
|
|
|
1217
1220
|
if (isRumActive) {
|
|
1218
1221
|
// Give some time RUM to flush data, similar to what we do in selenium
|
|
1219
|
-
await new Promise(resolve =>
|
|
1222
|
+
await new Promise(resolve => realSetTimeout(resolve, RUM_FLUSH_WAIT_TIME))
|
|
1220
1223
|
const url = page.url()
|
|
1221
1224
|
if (url) {
|
|
1222
1225
|
const domain = new URL(url).hostname
|
|
@@ -136,11 +136,10 @@ function resolveClientDbConfig (clientConfig, datasourceName, runtimeDbConfig) {
|
|
|
136
136
|
/**
|
|
137
137
|
* @param {unknown} runtime
|
|
138
138
|
* @param {string} versions
|
|
139
|
-
* @param {string} [name]
|
|
140
139
|
* @param {boolean} [isIitm]
|
|
141
140
|
* @returns {object}
|
|
142
141
|
*/
|
|
143
|
-
const prismaHook = (runtime, versions,
|
|
142
|
+
const prismaHook = (runtime, versions, isIitm) => {
|
|
144
143
|
/**
|
|
145
144
|
* @typedef {{ getPrismaClient?: (config: PrismaRuntimeConfig, ...args: unknown[]) => Function }} PrismaRuntime
|
|
146
145
|
*/
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
// Capture real timers at module load time, before any test can install fake timers.
|
|
4
|
+
const realSetTimeout = setTimeout
|
|
5
|
+
|
|
3
6
|
const shimmer = require('../../datadog-shimmer')
|
|
4
7
|
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
5
8
|
const { addHook, channel } = require('./helpers/instrument')
|
|
@@ -66,7 +69,7 @@ addHook({
|
|
|
66
69
|
if (isRumActive) {
|
|
67
70
|
// We'll have time for RUM to flush the events (there's no callback to know when it's done)
|
|
68
71
|
await new Promise(resolve => {
|
|
69
|
-
|
|
72
|
+
realSetTimeout(() => {
|
|
70
73
|
resolve()
|
|
71
74
|
}, DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS)
|
|
72
75
|
})
|
|
@@ -6,7 +6,7 @@ const {
|
|
|
6
6
|
addHook,
|
|
7
7
|
} = require('./helpers/instrument')
|
|
8
8
|
|
|
9
|
-
addHook({ name: 'sequelize', versions: ['>=4'], file:
|
|
9
|
+
addHook({ name: 'sequelize', versions: ['>=4'], file: 'lib/sequelize.js' }, Sequelize => {
|
|
10
10
|
const startCh = channel('datadog:sequelize:query:start')
|
|
11
11
|
const finishCh = channel('datadog:sequelize:query:finish')
|
|
12
12
|
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const shimmer = require('../../datadog-shimmer')
|
|
4
4
|
const { addHook, channel } = require('./helpers/instrument')
|
|
5
|
-
const names = ['url', 'node:url']
|
|
6
|
-
|
|
7
5
|
const parseFinishedChannel = channel('datadog:url:parse:finish')
|
|
8
6
|
const urlGetterChannel = channel('datadog:url:getter:finish')
|
|
9
7
|
const instrumentedGetters = ['host', 'origin', 'hostname']
|
|
10
8
|
|
|
11
|
-
addHook({ name:
|
|
9
|
+
addHook({ name: 'url' }, function (url) {
|
|
12
10
|
shimmer.wrap(url, 'parse', (parse) => {
|
|
13
11
|
return function wrappedParse (input) {
|
|
14
12
|
const parsedValue = parse.apply(this, arguments)
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
|
|
3
|
+
// Capture real timers at module load time, before any test can install fake timers.
|
|
4
|
+
const realSetTimeout = setTimeout
|
|
5
|
+
|
|
2
6
|
const path = require('node:path')
|
|
3
7
|
|
|
4
8
|
const shimmer = require('../../datadog-shimmer')
|
|
@@ -83,7 +87,7 @@ function getTestCommand () {
|
|
|
83
87
|
|
|
84
88
|
function waitForHitProbe () {
|
|
85
89
|
return new Promise(resolve => {
|
|
86
|
-
|
|
90
|
+
realSetTimeout(() => {
|
|
87
91
|
resolve()
|
|
88
92
|
}, BREAKPOINT_HIT_GRACE_PERIOD_MS)
|
|
89
93
|
})
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const shimmer = require('../../datadog-shimmer')
|
|
4
4
|
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
-
const names = ['vm', 'node:vm']
|
|
6
|
-
|
|
7
5
|
const runScriptStartChannel = channel('datadog:vm:run-script:start')
|
|
8
6
|
const sourceTextModuleStartChannel = channel('datadog:vm:source-text-module:start')
|
|
9
7
|
|
|
10
|
-
addHook({ name:
|
|
8
|
+
addHook({ name: 'vm' }, function (vm) {
|
|
11
9
|
vm.Script = class extends vm.Script {
|
|
12
10
|
constructor (code) {
|
|
13
11
|
super(...arguments)
|
|
@@ -23,12 +23,13 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
23
23
|
return id
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
/** @type {import('../../dd-trace/src/config/config-types').ConfigProperties['cloudPayloadTagging']} */
|
|
26
27
|
get cloudTaggingConfig () {
|
|
27
28
|
return this._tracerConfig.cloudPayloadTagging
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
get payloadTaggingRules () {
|
|
31
|
-
return this.cloudTaggingConfig.rules
|
|
32
|
+
return this.cloudTaggingConfig.rules?.aws?.[this.constructor.id]
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
constructor (...args) {
|
|
@@ -78,7 +79,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
78
79
|
this.requestInject(span, request)
|
|
79
80
|
})
|
|
80
81
|
|
|
81
|
-
if (this.constructor.isPayloadReporter && this.cloudTaggingConfig.
|
|
82
|
+
if (this.constructor.isPayloadReporter && this.cloudTaggingConfig.request) {
|
|
82
83
|
const maxDepth = this.cloudTaggingConfig.maxDepth
|
|
83
84
|
const requestTags = tagsFromRequest(this.payloadTaggingRules, request.params, { maxDepth })
|
|
84
85
|
span.addTags(requestTags)
|
|
@@ -215,7 +216,7 @@ class BaseAwsSdkPlugin extends ClientPlugin {
|
|
|
215
216
|
|
|
216
217
|
span.addTags(tags)
|
|
217
218
|
|
|
218
|
-
if (this.constructor.isPayloadReporter && this.cloudTaggingConfig.
|
|
219
|
+
if (this.constructor.isPayloadReporter && this.cloudTaggingConfig.response) {
|
|
219
220
|
const maxDepth = this.cloudTaggingConfig.maxDepth
|
|
220
221
|
const responseBody = this.extractResponseBody(response)
|
|
221
222
|
const responseTags = tagsFromResponse(this.payloadTaggingRules, responseBody, { maxDepth })
|