dd-trace 5.110.0 → 5.111.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 (115) hide show
  1. package/README.md +13 -8
  2. package/ci/init.js +21 -2
  3. package/ci/vitest-no-worker-init-setup.mjs +430 -0
  4. package/ext/tags.js +2 -0
  5. package/index.d.ts +13 -0
  6. package/initialize.mjs +5 -6
  7. package/loader-hook.mjs +76 -55
  8. package/package.json +9 -9
  9. package/packages/datadog-instrumentations/src/fs.js +8 -6
  10. package/packages/datadog-instrumentations/src/graphql.js +26 -495
  11. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +201 -0
  12. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  13. package/packages/datadog-instrumentations/src/mongoose.js +14 -2
  14. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +1293 -0
  15. package/packages/datadog-instrumentations/src/vitest-main.js +1567 -0
  16. package/packages/datadog-instrumentations/src/vitest-util.js +249 -0
  17. package/packages/datadog-instrumentations/src/vitest-worker.js +753 -0
  18. package/packages/datadog-instrumentations/src/vitest.js +11 -1855
  19. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/client.js +2 -2
  20. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/context.js +18 -10
  21. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +47 -11
  22. package/packages/datadog-plugin-cucumber/src/index.js +1 -1
  23. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +10 -4
  24. package/packages/datadog-plugin-cypress/src/support.js +45 -1
  25. package/packages/datadog-plugin-express/src/code_origin.js +1 -1
  26. package/packages/datadog-plugin-fastify/src/code_origin.js +1 -1
  27. package/packages/datadog-plugin-graphql/src/execute.js +627 -11
  28. package/packages/datadog-plugin-graphql/src/index.js +20 -8
  29. package/packages/datadog-plugin-graphql/src/parse.js +24 -4
  30. package/packages/datadog-plugin-graphql/src/validate.js +16 -5
  31. package/packages/datadog-plugin-http/src/index.js +6 -8
  32. package/packages/datadog-plugin-jest/src/index.js +1 -1
  33. package/packages/datadog-plugin-mocha/src/index.js +1 -1
  34. package/packages/datadog-plugin-openai/src/services.js +2 -2
  35. package/packages/datadog-plugin-playwright/src/index.js +1 -1
  36. package/packages/datadog-plugin-vitest/src/index.js +69 -63
  37. package/packages/datadog-shimmer/src/shimmer.js +37 -16
  38. package/packages/dd-trace/src/aiguard/sdk.js +2 -2
  39. package/packages/dd-trace/src/appsec/api_security/sampler.js +3 -3
  40. package/packages/dd-trace/src/appsec/channels.js +3 -1
  41. package/packages/dd-trace/src/appsec/downstream_requests.js +4 -4
  42. package/packages/dd-trace/src/appsec/graphql.js +5 -5
  43. package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +26 -19
  44. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
  45. package/packages/dd-trace/src/appsec/iast/telemetry/index.js +2 -1
  46. package/packages/dd-trace/src/appsec/index.js +10 -1
  47. package/packages/dd-trace/src/appsec/lambda.js +135 -0
  48. package/packages/dd-trace/src/appsec/reporter.js +49 -10
  49. package/packages/dd-trace/src/appsec/telemetry/index.js +1 -1
  50. package/packages/dd-trace/src/appsec/waf/index.js +16 -4
  51. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +4 -4
  52. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +21 -6
  53. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +2 -2
  54. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
  55. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
  56. package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +3 -2
  57. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -1
  58. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +55 -13
  59. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +2 -2
  60. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/writer.js +17 -0
  61. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +47 -26
  62. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -2
  63. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +64 -53
  64. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +3 -3
  65. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +23 -5
  66. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +128 -0
  67. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +287 -0
  68. package/packages/dd-trace/src/config/defaults.js +3 -2
  69. package/packages/dd-trace/src/config/generated-config-types.d.ts +61 -57
  70. package/packages/dd-trace/src/config/helper.js +1 -0
  71. package/packages/dd-trace/src/config/index.js +35 -22
  72. package/packages/dd-trace/src/config/major-overrides.js +4 -2
  73. package/packages/dd-trace/src/config/remote_config.js +1 -1
  74. package/packages/dd-trace/src/config/supported-configurations.json +90 -56
  75. package/packages/dd-trace/src/constants.js +7 -0
  76. package/packages/dd-trace/src/datastreams/processor.js +11 -3
  77. package/packages/dd-trace/src/exporters/agent/index.js +1 -1
  78. package/packages/dd-trace/src/exporters/agentless/writer.js +4 -4
  79. package/packages/dd-trace/src/llmobs/index.js +1 -1
  80. package/packages/dd-trace/src/llmobs/plugins/base.js +4 -4
  81. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  82. package/packages/dd-trace/src/llmobs/sdk.js +3 -3
  83. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  84. package/packages/dd-trace/src/llmobs/tagger.js +3 -3
  85. package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
  86. package/packages/dd-trace/src/opentelemetry/metrics/index.js +54 -5
  87. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +40 -0
  88. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +169 -0
  89. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +38 -39
  90. package/packages/dd-trace/src/opentelemetry/trace/index.js +4 -0
  91. package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
  92. package/packages/dd-trace/src/opentracing/tracer.js +6 -1
  93. package/packages/dd-trace/src/plugin_manager.js +7 -7
  94. package/packages/dd-trace/src/plugins/ci_plugin.js +12 -3
  95. package/packages/dd-trace/src/plugins/util/llm.js +6 -1
  96. package/packages/dd-trace/src/plugins/util/test.js +11 -9
  97. package/packages/dd-trace/src/profiling/exporter_cli.js +2 -2
  98. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +3 -3
  99. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  100. package/packages/dd-trace/src/proxy.js +8 -8
  101. package/packages/dd-trace/src/span_processor.js +5 -6
  102. package/packages/dd-trace/src/span_stats.js +96 -78
  103. package/packages/dd-trace/src/startup-log.js +2 -1
  104. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  105. package/packages/dd-trace/src/telemetry/endpoints.js +6 -4
  106. package/packages/dd-trace/src/telemetry/index.js +2 -2
  107. package/packages/dd-trace/src/telemetry/logs/index.js +1 -1
  108. package/packages/dd-trace/src/telemetry/send-data.js +8 -8
  109. package/packages/dd-trace/src/telemetry/session-propagation.js +1 -1
  110. package/packages/dd-trace/src/telemetry/telemetry.js +9 -9
  111. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  112. package/vendor/dist/protobufjs/index.js +1 -1
  113. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  114. package/vendor/dist/shell-quote/index.js +1 -1
  115. package/packages/datadog-plugin-graphql/src/resolve.js +0 -170
package/loader-hook.mjs CHANGED
@@ -13,12 +13,37 @@ import { isRelativeRequire } from './packages/datadog-instrumentations/src/helpe
13
13
 
14
14
  // This file must support Node.js 12.0.0 syntax
15
15
 
16
+ const { builtinModules } = Module
16
17
  const regexpEscape = regexpEscapeModule.default
17
18
  const require = Module.createRequire(import.meta.url)
18
19
  let syncImportInTheMiddleHook
19
20
 
20
- // For some reason `getEnvironmentVariable` is not otherwise available to ESM.
21
- const env = configHelper.getEnvironmentVariable
21
+ // The config helper's named exports aren't visible to ESM; destructure the default.
22
+ const { getValueFromEnvSources } = configHelper
23
+
24
+ // Substrings of resolved URLs that import-in-the-middle must never wrap: re-export
25
+ // shims and internal helper graphs that break when proxied, plus iitm's own files
26
+ // (via `middle`). One alternation so a single test() covers every excluded load.
27
+ export const iitmExclusionRegExp = /middle|langsmith|openai\/_shims|openai\/resources\/chat\/completions\/messages|openai\/agents-core\/dist\/shims|@anthropic-ai\/sdk\/_shims/
28
+
29
+ // Instrumented bare specifiers (`import 'express'`, builtins, symlinked or
30
+ // workspace packages) match against the specifier (the Set); their files inside
31
+ // node_modules match against the URL (the alternation). regexpEscape guards
32
+ // against a regex metacharacter entering a package name.
33
+ const includeModuleNames = new Set()
34
+ let moduleNameAlternation = ''
35
+ for (const moduleName of Object.keys(hooks)) {
36
+ // Relative hooks resolve outside node_modules and are not instrumented here.
37
+ if (isRelativeRequire(moduleName)) continue
38
+ includeModuleNames.add(moduleName)
39
+ // iitm matches a built-in by its node: specifier too, so mirror that and
40
+ // wrap `import 'node:crypto'` as well as `import 'crypto'`.
41
+ if (builtinModules.includes(moduleName)) includeModuleNames.add(`node:${moduleName}`)
42
+ if (moduleNameAlternation !== '') moduleNameAlternation += '|'
43
+ moduleNameAlternation += regexpEscape(moduleName)
44
+ }
45
+
46
+ const nodeModulesIncludeSource = `node_modules/(?:${moduleNameAlternation})/(?!node_modules).+`
22
47
 
23
48
  function initialize (data = {}) {
24
49
  prepareImportInTheMiddleOptions(data)
@@ -26,16 +51,59 @@ function initialize (data = {}) {
26
51
  }
27
52
 
28
53
  function prepareImportInTheMiddleOptions (data = {}) {
29
- if (data.include == null) data.include = []
30
- if (data.exclude == null) data.exclude = []
31
-
32
- addInstrumentations(data)
33
- addSecurityControls(data)
34
- addExclusions(data)
54
+ // A consumer-owned shouldInclude predicate takes over the wrapping decision, so
55
+ // iitm ignores the include/exclude arrays. Building the matcher here keeps the
56
+ // synchronous and asynchronous loaders on one matching implementation.
57
+ data.shouldInclude = createShouldInclude(getValueFromEnvSources('DD_IAST_SECURITY_CONTROLS_CONFIGURATION'))
35
58
 
36
59
  return data
37
60
  }
38
61
 
62
+ /**
63
+ * Builds the import-in-the-middle `shouldInclude(url, specifier)` predicate. iitm
64
+ * calls it for every resolved module and wraps the module when the result is
65
+ * truthy; supplying it replaces iitm's include/exclude list scan.
66
+ *
67
+ * @param {string} [securityControlsConfig] Raw `DD_IAST_SECURITY_CONTROLS_CONFIGURATION`;
68
+ * each entry's module path is instrumented in addition to the hook table.
69
+ */
70
+ function createShouldInclude (securityControlsConfig) {
71
+ const includeRegExp = new RegExp(buildIncludeSource(securityControlsConfig))
72
+
73
+ /**
74
+ * @param {string} url Resolved module URL (`file:`, `node:`, ...).
75
+ * @param {string} specifier Original import specifier.
76
+ */
77
+ return function shouldInclude (url, specifier) {
78
+ return (includeModuleNames.has(specifier) || includeRegExp.test(url)) && !iitmExclusionRegExp.test(url)
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Appends each `DD_IAST_SECURITY_CONTROLS_CONFIGURATION` module path — the third
84
+ * `:`-separated segment of every `;`-separated `<type>:<marks>:<module>:<...>` entry —
85
+ * to the include alternation, escaped.
86
+ *
87
+ * @param {string} [securityControlsConfig] Raw `DD_IAST_SECURITY_CONTROLS_CONFIGURATION`.
88
+ */
89
+ function buildIncludeSource (securityControlsConfig) {
90
+ if (!securityControlsConfig) return nodeModulesIncludeSource
91
+
92
+ let includeSource = nodeModulesIncludeSource
93
+ for (const entry of securityControlsConfig.split(';')) {
94
+ if (!entry) continue
95
+ const first = entry.indexOf(':')
96
+ if (first === -1) continue
97
+ const second = entry.indexOf(':', first + 1)
98
+ if (second === -1) continue
99
+ const third = entry.indexOf(':', second + 1)
100
+
101
+ const subpath = entry.slice(second + 1, third === -1 ? undefined : third).trim()
102
+ if (subpath) includeSource += `|${regexpEscape(subpath)}`
103
+ }
104
+ return includeSource
105
+ }
106
+
39
107
  function load (url, context, nextLoad) {
40
108
  return rewriterLoader.load(url, context, (url, context) => origLoad(url, context, nextLoad))
41
109
  }
@@ -113,51 +181,4 @@ function registerSyncLoaderHooks (data = {}) {
113
181
  return true
114
182
  }
115
183
 
116
- function addInstrumentations (data) {
117
- const instrumentations = Object.keys(hooks)
118
-
119
- for (const moduleName of instrumentations) {
120
- // Skip instrumentation hooks with relative module names
121
- // since there is no current business need of instrumenting imports outside of the node_modules folder
122
- if (!isRelativeRequire(moduleName)) {
123
- data.include.push(new RegExp(`node_modules/${moduleName}/(?!node_modules).+`), moduleName)
124
- }
125
- }
126
- }
127
-
128
- function addSecurityControls (data) {
129
- const raw = env('DD_IAST_SECURITY_CONTROLS_CONFIGURATION')
130
- if (!raw) return
131
- // Parse `;`-separated entries and take the 3rd `:`-separated segment.
132
- // Expected form (per entry): `<...>:<...>:<subpath>:<...>`
133
- const entries = raw.split(';')
134
- for (const entry of entries) {
135
- if (entry) {
136
- const first = entry.indexOf(':')
137
- if (first === -1) continue
138
- const second = entry.indexOf(':', first + 1)
139
- if (second === -1) continue
140
- const third = entry.indexOf(':', second + 1)
141
-
142
- const subpath = entry.slice(second + 1, third === -1 ? undefined : third).trim()
143
- if (subpath) {
144
- data.include.push(new RegExp(regexpEscape(subpath)))
145
- }
146
- }
147
- }
148
- }
149
-
150
- function addExclusions (data) {
151
- data.exclude.push(...iitmExclusions)
152
- }
153
-
154
- export const iitmExclusions = [
155
- /middle/,
156
- /langsmith/,
157
- /openai\/_shims/,
158
- /openai\/resources\/chat\/completions\/messages/,
159
- /openai\/agents-core\/dist\/shims/,
160
- /@anthropic-ai\/sdk\/_shims/,
161
- ]
162
-
163
184
  export { initialize, load, registerSyncLoaderHooks, resolve }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.110.0",
3
+ "version": "5.111.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -46,7 +46,7 @@
46
46
  "test:webpack:ci": "nyc --silent node init && nyc -- npm run test:webpack",
47
47
  "test:instrumentations": "mocha \"packages/datadog-instrumentations/test/@(${PLUGINS}).spec.js\"",
48
48
  "test:instrumentations:ci": "yarn services && nyc --silent node init && nyc -- npm run test:instrumentations",
49
- "test:instrumentations:misc": "mocha \"packages/datadog-instrumentations/test/*/**/*.spec.js\"",
49
+ "test:instrumentations:misc": "mocha \"packages/datadog-instrumentations/test/*/**/*.spec.{js,mjs}\"",
50
50
  "test:instrumentations:misc:ci": "nyc --silent node init && nyc -- npm run test:instrumentations:misc",
51
51
  "test:core": "node scripts/mocha-parallel-files.js --expose-gc --timeout 30000 -- \"packages/datadog-core/test/**/*.spec.js\"",
52
52
  "test:core:ci": "nyc --silent node init && nyc -- npm run test:core",
@@ -104,7 +104,7 @@
104
104
  "test:integration:plugins:coverage": "yarn services && node ./integration-tests/coverage/run-suite.js \"packages/datadog-plugin-@(${PLUGINS})/test/integration-test/**/${SPEC:-*}*.spec.js\"",
105
105
  "test:unit:plugins": "mocha \"packages/datadog-instrumentations/test/@(${PLUGINS}).spec.js\" \"packages/datadog-plugin-@(${PLUGINS})/test/**/*.spec.js\" --exclude \"packages/datadog-plugin-@(${PLUGINS})/test/integration-test/**/*.spec.js\"",
106
106
  "test:release": "mocha \"scripts/release/**/*.spec.js\"",
107
- "test:scripts": "mocha \"scripts/helpers/**/*.spec.js\"",
107
+ "test:scripts": "mocha \"scripts/helpers/**/*.spec.js\" \"scripts/*.spec.mjs\"",
108
108
  "test:shimmer": "mocha \"packages/datadog-shimmer/test/**/*.spec.js\"",
109
109
  "test:shimmer:ci": "nyc --silent node init && nyc -- npm run test:shimmer",
110
110
  "verify:workflow-job-names": "node scripts/verify-workflow-job-names.js",
@@ -164,7 +164,7 @@
164
164
  ],
165
165
  "dependencies": {
166
166
  "dc-polyfill": "^0.1.11",
167
- "import-in-the-middle": "^3.1.0",
167
+ "import-in-the-middle": "^3.2.0",
168
168
  "opentracing": ">=0.14.7"
169
169
  },
170
170
  "optionalDependencies": {
@@ -192,7 +192,7 @@
192
192
  "@types/mocha": "^10.0.10",
193
193
  "@types/node": "^18.19.106",
194
194
  "@types/sinon": "^21.0.1",
195
- "axios": "^1.18.0",
195
+ "axios": "^1.18.1",
196
196
  "benchmark": "^2.1.4",
197
197
  "body-parser": "^2.3.0",
198
198
  "bun": "1.3.14",
@@ -201,15 +201,15 @@
201
201
  "eslint": "^9.39.2",
202
202
  "eslint-plugin-cypress": "^6.4.1",
203
203
  "eslint-plugin-import": "^2.32.0",
204
- "eslint-plugin-jsdoc": "^63.0.6",
204
+ "eslint-plugin-jsdoc": "^63.0.8",
205
205
  "eslint-plugin-mocha": "^11.3.0",
206
- "eslint-plugin-n": "^18.1.0",
206
+ "eslint-plugin-n": "^18.2.0",
207
207
  "eslint-plugin-promise": "^7.3.0",
208
208
  "eslint-plugin-sonarjs": "^4.1.0",
209
209
  "eslint-plugin-unicorn": "^64.0.0",
210
210
  "express": "^5.1.0",
211
211
  "glob": "^10.4.5",
212
- "globals": "^17.2.0",
212
+ "globals": "^17.7.0",
213
213
  "graphql": "*",
214
214
  "husky": "^9.1.7",
215
215
  "istanbul-lib-report": "^3.0.0",
@@ -227,7 +227,7 @@
227
227
  "proxyquire": "^2.1.3",
228
228
  "retry": "^0.13.1",
229
229
  "semifies": "^1.0.0",
230
- "semver": "^7.8.4",
230
+ "semver": "^7.8.5",
231
231
  "sinon": "^22.0.0",
232
232
  "tiktoken": "^1.0.21",
233
233
  "typescript": "^6.0.3",
@@ -88,8 +88,10 @@ addHook({ name: 'fs' }, fs => {
88
88
  const asyncMethods = Object.keys(paramsByMethod)
89
89
  const syncMethods = asyncMethods.map(name => `${name}Sync`)
90
90
 
91
- massWrap(fs, asyncMethods, createWrapFunction())
92
- massWrap(fs, syncMethods, createWrapFunction())
91
+ // Node 20 defines `fs.opendir` / `fs.opendirSync` as lazy accessor properties;
92
+ // `replaceGetter` resolves the method so the call is wrapped, not the accessor.
93
+ massWrap(fs, asyncMethods, createWrapFunction(), { replaceGetter: true })
94
+ massWrap(fs, syncMethods, createWrapFunction(), { replaceGetter: true })
93
95
  massWrap(fs.promises, asyncMethods, createWrapFunction('promises.'))
94
96
 
95
97
  wrap(fs.realpath, 'native', createWrapFunction('', 'realpath.native'))
@@ -355,15 +357,15 @@ function getMessage (operation, params, args, self) {
355
357
  return { operation, ...metadata }
356
358
  }
357
359
 
358
- function massWrap (target, methods, wrapper) {
360
+ function massWrap (target, methods, wrapper, options) {
359
361
  for (const method of methods) {
360
- wrap(target, method, wrapper)
362
+ wrap(target, method, wrapper, options)
361
363
  }
362
364
  }
363
365
 
364
- function wrap (target, method, wrapper) {
366
+ function wrap (target, method, wrapper, options) {
365
367
  try {
366
- shimmer.wrap(target, method, wrapper)
368
+ shimmer.wrap(target, method, wrapper, options)
367
369
  } catch {
368
370
  // skip unavailable method
369
371
  }