dd-trace 5.95.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.
Files changed (124) hide show
  1. package/index.d.ts +43 -0
  2. package/package.json +10 -8
  3. package/packages/datadog-esbuild/index.js +20 -9
  4. package/packages/datadog-instrumentations/src/ai.js +112 -0
  5. package/packages/datadog-instrumentations/src/child_process.js +7 -17
  6. package/packages/datadog-instrumentations/src/crypto.js +1 -2
  7. package/packages/datadog-instrumentations/src/cucumber.js +4 -1
  8. package/packages/datadog-instrumentations/src/cypress-config.js +324 -0
  9. package/packages/datadog-instrumentations/src/cypress.js +86 -4
  10. package/packages/datadog-instrumentations/src/dns.js +1 -2
  11. package/packages/datadog-instrumentations/src/express.js +4 -4
  12. package/packages/datadog-instrumentations/src/fs.js +27 -29
  13. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  14. package/packages/datadog-instrumentations/src/helpers/ai-messages.js +182 -0
  15. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
  16. package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
  17. package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
  18. package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
  19. package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
  20. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +25 -0
  21. package/packages/datadog-instrumentations/src/http/client.js +2 -3
  22. package/packages/datadog-instrumentations/src/http/server.js +2 -5
  23. package/packages/datadog-instrumentations/src/http2/client.js +1 -3
  24. package/packages/datadog-instrumentations/src/http2/server.js +1 -3
  25. package/packages/datadog-instrumentations/src/jest.js +13 -4
  26. package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
  27. package/packages/datadog-instrumentations/src/mocha/utils.js +14 -1
  28. package/packages/datadog-instrumentations/src/net.js +2 -8
  29. package/packages/datadog-instrumentations/src/pino.js +1 -1
  30. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  31. package/packages/datadog-instrumentations/src/prisma.js +1 -2
  32. package/packages/datadog-instrumentations/src/selenium.js +4 -1
  33. package/packages/datadog-instrumentations/src/sequelize.js +1 -1
  34. package/packages/datadog-instrumentations/src/url.js +1 -3
  35. package/packages/datadog-instrumentations/src/vitest.js +5 -1
  36. package/packages/datadog-instrumentations/src/vm.js +1 -3
  37. package/packages/datadog-plugin-aws-sdk/src/base.js +4 -3
  38. package/packages/datadog-plugin-cucumber/src/index.js +7 -3
  39. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +57 -5
  40. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  41. package/packages/datadog-plugin-jest/src/index.js +4 -2
  42. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
  43. package/packages/datadog-plugin-mocha/src/index.js +5 -2
  44. package/packages/datadog-plugin-next/src/index.js +2 -14
  45. package/packages/datadog-plugin-openai/src/services.js +1 -0
  46. package/packages/datadog-webpack/index.js +3 -3
  47. package/packages/dd-trace/index.js +12 -10
  48. package/packages/dd-trace/src/agent/url.js +2 -2
  49. package/packages/dd-trace/src/aiguard/index.js +64 -0
  50. package/packages/dd-trace/src/aiguard/sdk.js +4 -0
  51. package/packages/dd-trace/src/appsec/blocking.js +3 -0
  52. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
  53. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
  54. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  55. package/packages/dd-trace/src/appsec/remote_config.js +1 -0
  56. package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
  57. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
  58. package/packages/dd-trace/src/ci-visibility/lage.js +39 -0
  59. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
  60. package/packages/dd-trace/src/config/defaults.js +316 -146
  61. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
  62. package/packages/dd-trace/src/config/helper.js +59 -10
  63. package/packages/dd-trace/src/config/index.js +570 -1503
  64. package/packages/dd-trace/src/config/parsers.js +256 -0
  65. package/packages/dd-trace/src/config/remote_config.js +59 -2
  66. package/packages/dd-trace/src/config/supported-configurations.json +367 -433
  67. package/packages/dd-trace/src/constants.js +1 -0
  68. package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
  69. package/packages/dd-trace/src/crashtracking/index.js +1 -7
  70. package/packages/dd-trace/src/debugger/index.js +1 -1
  71. package/packages/dd-trace/src/dogstatsd.js +12 -9
  72. package/packages/dd-trace/src/encode/0.4.js +1 -1
  73. package/packages/dd-trace/src/exporter.js +5 -2
  74. package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
  75. package/packages/dd-trace/src/exporters/common/request.js +9 -0
  76. package/packages/dd-trace/src/exporters/common/writer.js +12 -2
  77. package/packages/dd-trace/src/heap_snapshots.js +3 -0
  78. package/packages/dd-trace/src/index.js +5 -2
  79. package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
  80. package/packages/dd-trace/src/llmobs/constants/text.js +3 -0
  81. package/packages/dd-trace/src/llmobs/index.js +13 -5
  82. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
  83. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
  84. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
  85. package/packages/dd-trace/src/llmobs/sdk.js +12 -8
  86. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  87. package/packages/dd-trace/src/llmobs/tagger.js +9 -6
  88. package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
  89. package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
  90. package/packages/dd-trace/src/log/index.js +26 -55
  91. package/packages/dd-trace/src/log/writer.js +7 -19
  92. package/packages/dd-trace/src/noop/proxy.js +8 -0
  93. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  94. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  95. package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
  96. package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
  97. package/packages/dd-trace/src/plugin_manager.js +8 -6
  98. package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
  99. package/packages/dd-trace/src/plugins/plugin.js +7 -4
  100. package/packages/dd-trace/src/plugins/util/test.js +5 -0
  101. package/packages/dd-trace/src/process-tags/index.js +3 -0
  102. package/packages/dd-trace/src/profiler.js +27 -2
  103. package/packages/dd-trace/src/profiling/config.js +73 -241
  104. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
  105. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
  106. package/packages/dd-trace/src/profiling/profiler.js +56 -44
  107. package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
  108. package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
  109. package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
  110. package/packages/dd-trace/src/propagation-hash/index.js +2 -1
  111. package/packages/dd-trace/src/proxy.js +36 -3
  112. package/packages/dd-trace/src/remote_config/index.js +3 -0
  113. package/packages/dd-trace/src/require-package-json.js +8 -4
  114. package/packages/dd-trace/src/ritm.js +58 -26
  115. package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
  116. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -0
  117. package/packages/dd-trace/src/sampler.js +1 -1
  118. package/packages/dd-trace/src/standalone/index.js +3 -0
  119. package/packages/dd-trace/src/startup-log.js +9 -0
  120. package/packages/dd-trace/src/telemetry/index.js +2 -3
  121. package/packages/dd-trace/src/telemetry/send-data.js +5 -19
  122. package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
  123. package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
  124. package/packages/dd-trace/src/util.js +0 -9
@@ -0,0 +1,324 @@
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+ const os = require('os')
5
+ const path = require('path')
6
+ const { pathToFileURL } = require('url')
7
+
8
+ const DD_CONFIG_WRAPPED = Symbol('dd-trace.cypress.config.wrapped')
9
+
10
+ const noopTask = {
11
+ 'dd:testSuiteStart': () => null,
12
+ 'dd:beforeEach': () => ({}),
13
+ 'dd:afterEach': () => null,
14
+ 'dd:addTags': () => null,
15
+ 'dd:log': () => null,
16
+ }
17
+
18
+ /**
19
+ * @param {unknown} value
20
+ * @returns {boolean}
21
+ */
22
+ function isPlainObject (value) {
23
+ if (!value || typeof value !== 'object') return false
24
+ const prototype = Object.getPrototypeOf(value)
25
+ return prototype === Object.prototype || prototype === null
26
+ }
27
+
28
+ /**
29
+ * Cypress allows setupNodeEvents to return partial config fragments that it
30
+ * diffs and merges into the resolved config. Preserve that behavior here so
31
+ * the wrapper does not drop user-provided config updates.
32
+ *
33
+ * @param {object} config Cypress resolved config object
34
+ * @param {unknown} updatedConfig value returned from setupNodeEvents
35
+ * @returns {object} resolved config with returned overrides applied
36
+ */
37
+ function mergeReturnedConfig (config, updatedConfig) {
38
+ if (!isPlainObject(updatedConfig) || updatedConfig === config) {
39
+ return config
40
+ }
41
+
42
+ const mergedConfig = { ...config }
43
+
44
+ for (const [key, value] of Object.entries(updatedConfig)) {
45
+ mergedConfig[key] = isPlainObject(value) && isPlainObject(mergedConfig[key])
46
+ ? mergeReturnedConfig(mergedConfig[key], value)
47
+ : value
48
+ }
49
+
50
+ return mergedConfig
51
+ }
52
+
53
+ /**
54
+ * Creates a temporary wrapper support file under os.tmpdir() that loads
55
+ * dd-trace's browser-side hooks before the user's original support file.
56
+ * Returns the wrapper path (for cleanup) or undefined if injection was skipped.
57
+ *
58
+ * @param {object} config Cypress resolved config object
59
+ * @returns {string|undefined} wrapper file path, or undefined if skipped
60
+ */
61
+ function injectSupportFile (config) {
62
+ const originalSupportFile = config.supportFile
63
+ if (!originalSupportFile || originalSupportFile === false) return
64
+
65
+ try {
66
+ const content = fs.readFileSync(originalSupportFile, 'utf8')
67
+ // Naive check: skip lines starting with // or * to avoid matching commented-out imports.
68
+ const hasActiveDdTraceImport = content.split('\n').some(line => {
69
+ const trimmed = line.trim()
70
+ return trimmed.includes('dd-trace/ci/cypress/support') &&
71
+ !trimmed.startsWith('//') && !trimmed.startsWith('*')
72
+ })
73
+ if (hasActiveDdTraceImport) return
74
+ } catch {
75
+ return
76
+ }
77
+
78
+ const ddSupportFile = require.resolve('../../../ci/cypress/support')
79
+ const wrapperFile = path.join(os.tmpdir(), `dd-cypress-support-${process.pid}.mjs`)
80
+
81
+ // Always use ESM: it can import both CJS and ESM support files.
82
+ const wrapperContent =
83
+ `import ${JSON.stringify(ddSupportFile)}\nimport ${JSON.stringify(originalSupportFile)}\n`
84
+
85
+ try {
86
+ fs.writeFileSync(wrapperFile, wrapperContent)
87
+ config.supportFile = wrapperFile
88
+ return wrapperFile
89
+ } catch {
90
+ // Can't write wrapper - skip injection
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Registers dd-trace's Cypress hooks (before:run, after:spec, after:run, tasks)
96
+ * and injects the support file. Handles chaining with user-registered handlers
97
+ * for after:spec/after:run so both the user's code and dd-trace's run in sequence.
98
+ *
99
+ * @param {Function} on Cypress event registration function
100
+ * @param {object} config Cypress resolved config object
101
+ * @param {Function[]} userAfterSpecHandlers user's after:spec handlers collected from wrappedOn
102
+ * @param {Function[]} userAfterRunHandlers user's after:run handlers collected from wrappedOn
103
+ * @returns {object} the config object (possibly modified)
104
+ */
105
+ function registerDdTraceHooks (on, config, userAfterSpecHandlers, userAfterRunHandlers) {
106
+ const wrapperFile = injectSupportFile(config)
107
+
108
+ const cleanupWrapper = () => {
109
+ if (wrapperFile) {
110
+ try { fs.unlinkSync(wrapperFile) } catch { /* best effort */ }
111
+ }
112
+ }
113
+
114
+ const tracer = global._ddtrace
115
+
116
+ const registerAfterRunWithCleanup = () => {
117
+ on('after:run', (results) => {
118
+ const chain = userAfterRunHandlers.reduce(
119
+ (p, h) => p.then(() => h(results)),
120
+ Promise.resolve()
121
+ )
122
+ return chain.finally(cleanupWrapper)
123
+ })
124
+ }
125
+
126
+ const registerNoopHandlers = () => {
127
+ for (const h of userAfterSpecHandlers) on('after:spec', h)
128
+ registerAfterRunWithCleanup()
129
+ on('task', noopTask)
130
+ }
131
+
132
+ if (!tracer || !tracer._initialized) {
133
+ registerNoopHandlers()
134
+ return config
135
+ }
136
+
137
+ const NoopTracer = require('../../../packages/dd-trace/src/noop/tracer')
138
+
139
+ if (tracer._tracer instanceof NoopTracer) {
140
+ registerNoopHandlers()
141
+ return config
142
+ }
143
+
144
+ const cypressPlugin = require('../../../packages/datadog-plugin-cypress/src/cypress-plugin')
145
+
146
+ if (cypressPlugin._isInit) {
147
+ for (const h of userAfterSpecHandlers) on('after:spec', h)
148
+ registerAfterRunWithCleanup()
149
+ return config
150
+ }
151
+
152
+ on('before:run', cypressPlugin.beforeRun.bind(cypressPlugin))
153
+
154
+ on('after:spec', (spec, results) => {
155
+ const chain = userAfterSpecHandlers.reduce(
156
+ (p, h) => p.then(() => h(spec, results)),
157
+ Promise.resolve()
158
+ )
159
+ return chain.then(() => cypressPlugin.afterSpec(spec, results))
160
+ })
161
+
162
+ on('after:run', (results) => {
163
+ const chain = userAfterRunHandlers.reduce(
164
+ (p, h) => p.then(() => h(results)),
165
+ Promise.resolve()
166
+ )
167
+ return chain
168
+ .then(() => cypressPlugin.afterRun(results))
169
+ .finally(cleanupWrapper)
170
+ })
171
+
172
+ on('task', cypressPlugin.getTasks())
173
+
174
+ return Promise.resolve(cypressPlugin.init(tracer, config)).then(() => config)
175
+ }
176
+
177
+ /**
178
+ * @param {Function|undefined} originalSetupNodeEvents
179
+ * @returns {Function}
180
+ */
181
+ function wrapSetupNodeEvents (originalSetupNodeEvents) {
182
+ return function ddSetupNodeEvents (on, config) {
183
+ const userAfterSpecHandlers = []
184
+ const userAfterRunHandlers = []
185
+
186
+ const wrappedOn = (event, handler) => {
187
+ if (event === 'after:spec') {
188
+ userAfterSpecHandlers.push(handler)
189
+ } else if (event === 'after:run') {
190
+ userAfterRunHandlers.push(handler)
191
+ } else {
192
+ on(event, handler)
193
+ }
194
+ }
195
+
196
+ const maybePromise = originalSetupNodeEvents
197
+ ? originalSetupNodeEvents.call(this, wrappedOn, config)
198
+ : undefined
199
+
200
+ if (maybePromise && typeof maybePromise.then === 'function') {
201
+ return maybePromise.then((result) => {
202
+ return registerDdTraceHooks(
203
+ on,
204
+ mergeReturnedConfig(config, result),
205
+ userAfterSpecHandlers,
206
+ userAfterRunHandlers
207
+ )
208
+ })
209
+ }
210
+
211
+ return registerDdTraceHooks(
212
+ on,
213
+ mergeReturnedConfig(config, maybePromise),
214
+ userAfterSpecHandlers,
215
+ userAfterRunHandlers
216
+ )
217
+ }
218
+ }
219
+
220
+ /**
221
+ * @param {object} config
222
+ * @returns {object}
223
+ */
224
+ function wrapConfig (config) {
225
+ if (!config || config[DD_CONFIG_WRAPPED]) return config
226
+ config[DD_CONFIG_WRAPPED] = true
227
+
228
+ if (config.e2e) {
229
+ config.e2e.setupNodeEvents = wrapSetupNodeEvents(config.e2e.setupNodeEvents)
230
+ }
231
+ if (config.component) {
232
+ config.component.setupNodeEvents = wrapSetupNodeEvents(config.component.setupNodeEvents)
233
+ }
234
+
235
+ return config
236
+ }
237
+
238
+ /**
239
+ * @param {string} originalConfigFile absolute path to the original config file
240
+ * @returns {string} path to the generated wrapper file
241
+ */
242
+ function createConfigWrapper (originalConfigFile) {
243
+ const wrapperFile = path.join(
244
+ path.dirname(originalConfigFile),
245
+ `.dd-cypress-config-${process.pid}.mjs`
246
+ )
247
+
248
+ const cypressConfigPath = require.resolve('./cypress-config')
249
+
250
+ // Always use ESM: it can import both CJS and ESM configs, so it works
251
+ // regardless of the original file's extension or "type": "module" in package.json.
252
+ // Import cypress-config.js directly (CJS default = module.exports object).
253
+ fs.writeFileSync(wrapperFile, [
254
+ `import originalConfig from ${JSON.stringify(pathToFileURL(originalConfigFile).href)}`,
255
+ `import cypressConfig from ${JSON.stringify(pathToFileURL(cypressConfigPath).href)}`,
256
+ '',
257
+ 'export default cypressConfig.wrapConfig(originalConfig)',
258
+ '',
259
+ ].join('\n'))
260
+
261
+ return wrapperFile
262
+ }
263
+
264
+ /**
265
+ * Wraps the Cypress config file for a CLI start() call. When an explicit
266
+ * configFile is provided, creates a temp wrapper that imports the original
267
+ * and passes it through wrapConfig. This handles ESM configs (.mjs) and
268
+ * plain-object configs (without defineConfig) that can't be intercepted
269
+ * via the defineConfig shimmer.
270
+ *
271
+ * @param {object|undefined} options
272
+ * @returns {{ options: object|undefined, cleanup: Function }}
273
+ */
274
+ function wrapCliConfigFileOptions (options) {
275
+ const noop = { options, cleanup: () => {} }
276
+
277
+ if (!options) return noop
278
+
279
+ const projectRoot = typeof options.project === 'string' ? options.project : process.cwd()
280
+ let configFilePath
281
+
282
+ if (options.configFile === false) {
283
+ // configFile: false means "no config file" — respect Cypress's semantics
284
+ return noop
285
+ } else if (typeof options.configFile === 'string') {
286
+ configFilePath = path.isAbsolute(options.configFile)
287
+ ? options.configFile
288
+ : path.resolve(projectRoot, options.configFile)
289
+ } else {
290
+ // No explicit --config-file: resolve the default cypress.config.{js,ts,cjs,mjs}
291
+ for (const ext of ['.js', '.ts', '.cjs', '.mjs']) {
292
+ const candidate = path.join(projectRoot, `cypress.config${ext}`)
293
+ if (fs.existsSync(candidate)) {
294
+ configFilePath = candidate
295
+ break
296
+ }
297
+ }
298
+ }
299
+
300
+ // Skip .ts files — Cypress transpiles them internally via its own loader.
301
+ // The ESM wrapper can't import .ts directly. The defineConfig shimmer
302
+ // handles .ts configs since they're transpiled to CJS by Cypress.
303
+ if (!configFilePath || !fs.existsSync(configFilePath) || path.extname(configFilePath) === '.ts') return noop
304
+
305
+ try {
306
+ const wrapperFile = createConfigWrapper(configFilePath)
307
+
308
+ return {
309
+ options: { ...options, configFile: wrapperFile },
310
+ cleanup: () => {
311
+ try { fs.unlinkSync(wrapperFile) } catch { /* best effort */ }
312
+ },
313
+ }
314
+ } catch {
315
+ // Config directory may be read-only — fall back to no wrapping.
316
+ // The defineConfig shimmer will still handle configs that use defineConfig.
317
+ return noop
318
+ }
319
+ }
320
+
321
+ module.exports = {
322
+ wrapCliConfigFileOptions,
323
+ wrapConfig,
324
+ }
@@ -1,11 +1,93 @@
1
1
  'use strict'
2
2
 
3
+ const shimmer = require('../../datadog-shimmer')
3
4
  const { DD_MAJOR } = require('../../../version')
4
5
  const { addHook } = require('./helpers/instrument')
6
+ const {
7
+ wrapCliConfigFileOptions,
8
+ wrapConfig,
9
+ } = require('./cypress-config')
5
10
 
6
- // No handler because this is only useful for testing.
7
- // Cypress plugin does not patch any library.
11
+ // Wrap defineConfig() so configs are instrumented when loaded in Cypress's
12
+ // config child process. This covers both CLI and programmatic usage with CJS configs.
8
13
  addHook({
9
14
  name: 'cypress',
10
- versions: DD_MAJOR >= 6 ? ['>=10.2.0'] : ['>=6.7.0'],
11
- }, lib => lib)
15
+ versions: ['>=10.2.0'],
16
+ }, (cypress) => {
17
+ if (typeof cypress.defineConfig === 'function') {
18
+ shimmer.wrap(cypress, 'defineConfig', (defineConfig) => function (config) {
19
+ wrapConfig(config)
20
+ return defineConfig(config)
21
+ })
22
+ }
23
+ return cypress
24
+ })
25
+
26
+ // Wrap the CLI entry points (cypress run / cypress open) to handle config files
27
+ // that can't be intercepted via the defineConfig shimmer: ESM configs (.mjs)
28
+ // and plain-object configs (without defineConfig).
29
+ function getCliStartWrapper (start) {
30
+ return function ddTraceCliStart (options) {
31
+ const { options: wrappedOptions, cleanup } = wrapCliConfigFileOptions(options)
32
+ const result = start.call(this, wrappedOptions)
33
+
34
+ if (result && typeof result.then === 'function') {
35
+ return result.finally(cleanup)
36
+ }
37
+
38
+ cleanup()
39
+ return result
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Wraps `start` on an object (or its `.default`) if present.
45
+ *
46
+ * @param {object} mod module exports
47
+ * @returns {object} mod
48
+ */
49
+ function wrapStartOnModule (mod) {
50
+ const target = mod.default || mod
51
+ if (typeof target.start === 'function') {
52
+ shimmer.wrap(target, 'start', getCliStartWrapper)
53
+ }
54
+ return mod
55
+ }
56
+
57
+ // Hook the CLI entry points where Cypress resolves and executes `run`/`open`.
58
+ // Cypress 10-14: lib/exec/{run,open}.js as separate files.
59
+ // Cypress 15-15.10: dist/exec/{run,open}.js as separate files.
60
+ // Cypress >=15.11: bundled into dist/cli-<hash>.js exporting runModule/openModule.
61
+ for (const file of ['lib/exec/run.js', 'lib/exec/open.js', 'dist/exec/run.js', 'dist/exec/open.js']) {
62
+ addHook({
63
+ name: 'cypress',
64
+ versions: ['>=10.2.0'],
65
+ file,
66
+ }, wrapStartOnModule)
67
+ }
68
+
69
+ // Cypress >=15.11 bundles run/open into a single CLI chunk (dist/cli-<hash>.js).
70
+ // The chunk exports runModule and openModule, each with a start() method.
71
+ addHook({
72
+ name: 'cypress',
73
+ versions: ['>=10.2.0'],
74
+ filePattern: 'dist/cli.*',
75
+ }, (cliChunk) => {
76
+ if (cliChunk.runModule?.start) {
77
+ shimmer.wrap(cliChunk.runModule, 'start', getCliStartWrapper)
78
+ }
79
+ if (cliChunk.openModule?.start) {
80
+ shimmer.wrap(cliChunk.openModule, 'start', getCliStartWrapper)
81
+ }
82
+ return cliChunk
83
+ })
84
+
85
+ // Cypress <10 uses the old pluginsFile approach. No auto-instrumentation;
86
+ // users must use the manual dd-trace/ci/cypress/plugin setup.
87
+ // This hook is kept so the plugin system registers Cypress for version tracking.
88
+ if (DD_MAJOR < 6) {
89
+ addHook({
90
+ name: 'cypress',
91
+ versions: ['>=6.7.0 <10.2.0'],
92
+ }, lib => lib)
93
+ }
@@ -18,9 +18,8 @@ const rrtypes = {
18
18
  }
19
19
 
20
20
  const rrtypeMap = new WeakMap()
21
- const names = ['dns', 'node:dns']
22
21
 
23
- addHook({ name: names }, dns => {
22
+ addHook({ name: 'dns' }, dns => {
24
23
  shimmer.wrap(dns, 'lookup', fn => wrap('apm:dns:lookup', fn, 2))
25
24
  shimmer.wrap(dns, 'lookupService', fn => wrap('apm:dns:lookup_service', fn, 2))
26
25
  shimmer.wrap(dns, 'resolve', fn => wrap('apm:dns:resolve', fn, 2))
@@ -146,7 +146,7 @@ function wrapAppUse (use) {
146
146
  }
147
147
  }
148
148
 
149
- addHook({ name: 'express', versions: ['>=4'], file: ['lib/express.js'] }, express => {
149
+ addHook({ name: 'express', versions: ['>=4'], file: 'lib/express.js' }, express => {
150
150
  shimmer.wrap(express.application, 'handle', wrapHandle)
151
151
  shimmer.wrap(express.application, 'all', wrapAppAll)
152
152
  shimmer.wrap(express.application, 'route', wrapAppRoute)
@@ -224,19 +224,19 @@ function wrapProcessParamsMethod (requestPositionInArguments) {
224
224
  }
225
225
  }
226
226
 
227
- addHook({ name: 'express', versions: ['>=4.0.0 <4.3.0'], file: ['lib/express.js'] }, express => {
227
+ addHook({ name: 'express', versions: ['>=4.0.0 <4.3.0'], file: 'lib/express.js' }, express => {
228
228
  shimmer.wrap(express.Router, 'process_params', wrapProcessParamsMethod(1))
229
229
  return express
230
230
  })
231
231
 
232
- addHook({ name: 'express', versions: ['>=4.3.0 <5.0.0'], file: ['lib/express.js'] }, express => {
232
+ addHook({ name: 'express', versions: ['>=4.3.0 <5.0.0'], file: 'lib/express.js' }, express => {
233
233
  shimmer.wrap(express.Router, 'process_params', wrapProcessParamsMethod(2))
234
234
  return express
235
235
  })
236
236
 
237
237
  const queryReadCh = channel('datadog:express:query:finish')
238
238
 
239
- addHook({ name: 'express', file: ['lib/request.js'], versions: ['>=5.0.0'] }, request => {
239
+ addHook({ name: 'express', file: 'lib/request.js', versions: ['>=5.0.0'] }, request => {
240
240
  shimmer.wrap(request, 'query', function (originalGet) {
241
241
  return function wrappedGet () {
242
242
  const query = originalGet.call(this)
@@ -84,37 +84,35 @@ const paramsByFileHandleMethods = {
84
84
  writeFile: ['data', 'options'],
85
85
  writev: ['buffers', 'position'],
86
86
  }
87
- const names = ['fs', 'node:fs']
88
- for (const name of names) {
89
- addHook({ name }, fs => {
90
- const asyncMethods = Object.keys(paramsByMethod)
91
- const syncMethods = asyncMethods.map(name => `${name}Sync`)
92
-
93
- massWrap(fs, asyncMethods, createWrapFunction())
94
- massWrap(fs, syncMethods, createWrapFunction())
95
- massWrap(fs.promises, asyncMethods, createWrapFunction('promises.'))
96
-
97
- wrap(fs.realpath, 'native', createWrapFunction('', 'realpath.native'))
98
- wrap(fs.realpathSync, 'native', createWrapFunction('', 'realpath.native'))
99
- wrap(fs.promises.realpath, 'native', createWrapFunction('', 'realpath.native'))
100
-
101
- wrap(fs, 'createReadStream', wrapCreateStream)
102
- wrap(fs, 'createWriteStream', wrapCreateStream)
103
- if (fs.Dir) {
104
- wrap(fs.Dir.prototype, 'close', createWrapFunction('dir.'))
105
- wrap(fs.Dir.prototype, 'closeSync', createWrapFunction('dir.'))
106
- wrap(fs.Dir.prototype, 'read', createWrapFunction('dir.'))
107
- wrap(fs.Dir.prototype, 'readSync', createWrapFunction('dir.'))
108
- wrap(fs.Dir.prototype, Symbol.asyncIterator, createWrapDirAsyncIterator())
109
- }
87
+ addHook({ name: 'fs' }, fs => {
88
+ const asyncMethods = Object.keys(paramsByMethod)
89
+ const syncMethods = asyncMethods.map(name => `${name}Sync`)
90
+
91
+ massWrap(fs, asyncMethods, createWrapFunction())
92
+ massWrap(fs, syncMethods, createWrapFunction())
93
+ massWrap(fs.promises, asyncMethods, createWrapFunction('promises.'))
94
+
95
+ wrap(fs.realpath, 'native', createWrapFunction('', 'realpath.native'))
96
+ wrap(fs.realpathSync, 'native', createWrapFunction('', 'realpath.native'))
97
+ wrap(fs.promises.realpath, 'native', createWrapFunction('', 'realpath.native'))
98
+
99
+ wrap(fs, 'createReadStream', wrapCreateStream)
100
+ wrap(fs, 'createWriteStream', wrapCreateStream)
101
+ if (fs.Dir) {
102
+ wrap(fs.Dir.prototype, 'close', createWrapFunction('dir.'))
103
+ wrap(fs.Dir.prototype, 'closeSync', createWrapFunction('dir.'))
104
+ wrap(fs.Dir.prototype, 'read', createWrapFunction('dir.'))
105
+ wrap(fs.Dir.prototype, 'readSync', createWrapFunction('dir.'))
106
+ wrap(fs.Dir.prototype, Symbol.asyncIterator, createWrapDirAsyncIterator())
107
+ }
110
108
 
111
- wrap(fs, 'unwatchFile', createWatchWrapFunction())
112
- wrap(fs, 'watch', createWatchWrapFunction())
113
- wrap(fs, 'watchFile', createWatchWrapFunction())
109
+ wrap(fs, 'unwatchFile', createWatchWrapFunction())
110
+ wrap(fs, 'watch', createWatchWrapFunction())
111
+ wrap(fs, 'watchFile', createWatchWrapFunction())
112
+
113
+ return fs
114
+ })
114
115
 
115
- return fs
116
- })
117
- }
118
116
  function isFirstMethodReturningFileHandle (original) {
119
117
  return !kHandle && original.name === 'open'
120
118
  }
@@ -171,7 +171,7 @@ function wrapExecute (execute) {
171
171
  args,
172
172
  docSource: documentSources.get(document),
173
173
  source,
174
- fields: {},
174
+ fields: Object.create(null),
175
175
  abortController: new AbortController(),
176
176
  }
177
177