dd-trace 6.8.0 → 6.9.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 (179) hide show
  1. package/ci/diagnose.js +27 -25
  2. package/ci/init.js +6 -6
  3. package/ci/runbook.md +114 -20
  4. package/ci/test-optimization-validation/approval-artifacts.js +36 -3
  5. package/ci/test-optimization-validation/approval.js +78 -22
  6. package/ci/test-optimization-validation/blocker-category.js +24 -0
  7. package/ci/test-optimization-validation/ci-discovery.js +23 -17
  8. package/ci/test-optimization-validation/ci-package-scripts.js +34 -6
  9. package/ci/test-optimization-validation/ci-remediation.js +1 -1
  10. package/ci/test-optimization-validation/cli.js +280 -52
  11. package/ci/test-optimization-validation/command-blocker.js +159 -20
  12. package/ci/test-optimization-validation/command-output-policy.js +9 -3
  13. package/ci/test-optimization-validation/command-runner.js +9 -7
  14. package/ci/test-optimization-validation/environment.js +4 -2
  15. package/ci/test-optimization-validation/executable.js +15 -13
  16. package/ci/test-optimization-validation/execution-lock.js +70 -0
  17. package/ci/test-optimization-validation/framework-adapters/cucumber-validation.json +3 -0
  18. package/ci/test-optimization-validation/framework-adapters/cucumber.js +657 -5
  19. package/ci/test-optimization-validation/framework-adapters/vitest.js +517 -0
  20. package/ci/test-optimization-validation/generated-files.js +38 -28
  21. package/ci/test-optimization-validation/generated-test-contract.js +8 -4
  22. package/ci/test-optimization-validation/generated-verifier.js +24 -17
  23. package/ci/test-optimization-validation/literal-glob.js +52 -0
  24. package/ci/test-optimization-validation/manifest-loader.js +3 -0
  25. package/ci/test-optimization-validation/manifest-scaffold.js +300 -50
  26. package/ci/test-optimization-validation/manifest-schema.js +80 -17
  27. package/ci/test-optimization-validation/offline-fixtures.js +13 -4
  28. package/ci/test-optimization-validation/package-check.js +94 -0
  29. package/ci/test-optimization-validation/plan-writer.js +183 -10
  30. package/ci/test-optimization-validation/preflight-runner.js +110 -31
  31. package/ci/test-optimization-validation/project-build-artifact.js +31 -0
  32. package/ci/test-optimization-validation/redaction.js +18 -27
  33. package/ci/test-optimization-validation/report-writer.js +182 -48
  34. package/ci/test-optimization-validation/result-semantics.js +20 -3
  35. package/ci/test-optimization-validation/runner-command.js +40 -20
  36. package/ci/test-optimization-validation/runner-contract.js +79 -43
  37. package/ci/test-optimization-validation/scenarios/basic-reporting.js +59 -5
  38. package/ci/test-optimization-validation/scenarios/ci-wiring.js +141 -35
  39. package/ci/test-optimization-validation/scenarios/helpers.js +30 -6
  40. package/ci/test-optimization-validation/static-diagnosis.js +10 -3
  41. package/ci/test-optimization-validation/test-output.js +2 -1
  42. package/ci/test-optimization-validation/validation-blocker.js +21 -0
  43. package/ci/vitest-no-worker-init-setup.mjs +30 -34
  44. package/index.d.ts +98 -1
  45. package/init.js +1 -17
  46. package/initialize.mjs +11 -0
  47. package/loader-hook.mjs +6 -4
  48. package/package.json +5 -3
  49. package/packages/datadog-core/src/utils/src/parse-tags.js +0 -1
  50. package/packages/datadog-esbuild/src/utils.js +16 -1
  51. package/packages/datadog-instrumentations/src/ai.js +61 -34
  52. package/packages/datadog-instrumentations/src/bluebird.js +6 -6
  53. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +81 -5
  54. package/packages/datadog-instrumentations/src/cucumber.js +124 -47
  55. package/packages/datadog-instrumentations/src/dns.js +21 -2
  56. package/packages/datadog-instrumentations/src/electron.js +1 -0
  57. package/packages/datadog-instrumentations/src/fastify.js +3 -1
  58. package/packages/datadog-instrumentations/src/grpc/client.js +4 -2
  59. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +3 -1
  60. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  61. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +33 -9
  62. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +118 -0
  63. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +20 -2
  64. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +32 -0
  65. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +61 -0
  66. package/packages/datadog-instrumentations/src/helpers/router-helper.js +37 -6
  67. package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +1 -1
  68. package/packages/datadog-instrumentations/src/jest.js +979 -233
  69. package/packages/datadog-instrumentations/src/mocha/main.js +107 -9
  70. package/packages/datadog-instrumentations/src/mocha/utils.js +64 -42
  71. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +25 -0
  72. package/packages/datadog-instrumentations/src/mocha/worker.js +12 -18
  73. package/packages/datadog-instrumentations/src/mysql.js +1 -1
  74. package/packages/datadog-instrumentations/src/next.js +155 -23
  75. package/packages/datadog-instrumentations/src/openai.js +14 -0
  76. package/packages/datadog-instrumentations/src/pg.js +180 -6
  77. package/packages/datadog-instrumentations/src/playwright.js +173 -79
  78. package/packages/datadog-instrumentations/src/promise-js.js +4 -4
  79. package/packages/datadog-instrumentations/src/promise.js +3 -3
  80. package/packages/datadog-instrumentations/src/router.js +195 -19
  81. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +43 -10
  82. package/packages/datadog-instrumentations/src/vitest-main.js +360 -56
  83. package/packages/datadog-instrumentations/src/vitest-util.js +42 -7
  84. package/packages/datadog-instrumentations/src/vitest-worker.js +234 -17
  85. package/packages/datadog-instrumentations/src/webdriverio.js +194 -18
  86. package/packages/datadog-instrumentations/src/when.js +3 -3
  87. package/packages/datadog-instrumentations/src/ws.js +5 -1
  88. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +59 -48
  89. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -3
  90. package/packages/datadog-plugin-cucumber/src/index.js +5 -1
  91. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +50 -46
  92. package/packages/datadog-plugin-cypress/src/support.js +7 -4
  93. package/packages/datadog-plugin-electron/src/net.js +10 -4
  94. package/packages/datadog-plugin-http/src/client.js +1 -1
  95. package/packages/datadog-plugin-http2/src/client.js +1 -1
  96. package/packages/datadog-plugin-jest/src/index.js +1 -18
  97. package/packages/datadog-plugin-jest/src/util.js +2 -0
  98. package/packages/datadog-plugin-kafkajs/src/producer.js +2 -1
  99. package/packages/datadog-plugin-mocha/src/index.js +318 -1
  100. package/packages/datadog-plugin-next/src/index.js +57 -9
  101. package/packages/datadog-plugin-openai/src/tracing.js +4 -0
  102. package/packages/datadog-plugin-pg/src/index.js +65 -1
  103. package/packages/datadog-plugin-playwright/src/index.js +1 -1
  104. package/packages/datadog-plugin-vitest/src/index.js +95 -7
  105. package/packages/datadog-shimmer/src/shimmer.js +6 -2
  106. package/packages/dd-trace/src/aiguard/sdk.js +3 -0
  107. package/packages/dd-trace/src/appsec/{blocking.js → blocking/index.js} +26 -6
  108. package/packages/dd-trace/src/appsec/handlers/auth.js +62 -0
  109. package/packages/dd-trace/src/appsec/handlers/http-request.js +215 -0
  110. package/packages/dd-trace/src/appsec/handlers/http-response.js +78 -0
  111. package/packages/dd-trace/src/appsec/handlers/http-shared.js +24 -0
  112. package/packages/dd-trace/src/appsec/handlers/payments.js +104 -0
  113. package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +1 -1
  114. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  115. package/packages/dd-trace/src/appsec/index.js +48 -476
  116. package/packages/dd-trace/src/appsec/sdk/track_event.js +9 -0
  117. package/packages/dd-trace/src/ci-visibility/coverage-report-discovery.js +46 -14
  118. package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +89 -0
  119. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +27 -13
  120. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +17 -0
  121. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +21 -1
  122. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +22 -7
  123. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +9 -14
  124. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +21 -5
  125. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache-schema.js +1 -1
  126. package/packages/dd-trace/src/ci-visibility/test-optimization-http-cache.js +5 -1
  127. package/packages/dd-trace/src/config/generated-config-types.d.ts +2 -0
  128. package/packages/dd-trace/src/config/helper.js +2 -0
  129. package/packages/dd-trace/src/config/index.js +16 -5
  130. package/packages/dd-trace/src/config/remote_config.js +1 -1
  131. package/packages/dd-trace/src/config/supported-configurations.json +8 -0
  132. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  133. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +0 -1
  134. package/packages/dd-trace/src/guardrails/apply-pm2-env.js +16 -0
  135. package/packages/dd-trace/src/guardrails/log.js +1 -10
  136. package/packages/dd-trace/src/llmobs/eval-metric.js +249 -0
  137. package/packages/dd-trace/src/llmobs/experiments/index.js +33 -25
  138. package/packages/dd-trace/src/llmobs/experiments/util.js +4 -2
  139. package/packages/dd-trace/src/llmobs/noop.js +2 -0
  140. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +1 -1
  141. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
  142. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +5 -5
  143. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  144. package/packages/dd-trace/src/llmobs/sdk.js +149 -68
  145. package/packages/dd-trace/src/llmobs/telemetry.js +18 -0
  146. package/packages/dd-trace/src/llmobs/writers/base.js +3 -0
  147. package/packages/dd-trace/src/llmobs/writers/util.js +2 -0
  148. package/packages/dd-trace/src/log/channels.js +1 -9
  149. package/packages/dd-trace/src/log/levels.js +12 -0
  150. package/packages/dd-trace/src/openfeature/writers/exposures.js +1 -1
  151. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  152. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +1 -1
  153. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +8 -4
  154. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
  155. package/packages/dd-trace/src/opentelemetry/span.js +4 -0
  156. package/packages/dd-trace/src/plugins/ci_plugin.js +21 -5
  157. package/packages/dd-trace/src/plugins/index.js +1 -0
  158. package/packages/dd-trace/src/plugins/util/ci.js +6 -0
  159. package/packages/dd-trace/src/plugins/util/git.js +6 -4
  160. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +2 -2
  161. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -1
  162. package/packages/dd-trace/src/plugins/util/stacktrace.js +3 -0
  163. package/packages/dd-trace/src/plugins/util/test.js +319 -75
  164. package/packages/dd-trace/src/plugins/util/url.js +1 -1
  165. package/packages/dd-trace/src/plugins/util/web.js +23 -1
  166. package/packages/dd-trace/src/profiler.js +1 -1
  167. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +1 -1
  168. package/packages/dd-trace/src/profiling/profilers/events.js +2 -2
  169. package/packages/dd-trace/src/proxy.js +1 -0
  170. package/packages/dd-trace/src/ritm.js +5 -0
  171. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +4 -2
  172. package/packages/dd-trace/src/sampling_rule.js +4 -2
  173. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +1 -1
  174. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +1 -1
  175. package/packages/dd-trace/src/telemetry/logs/index.js +3 -0
  176. package/packages/dd-trace/src/telemetry/telemetry.js +1 -1
  177. package/vendor/dist/pprof-format/index.js +1 -1
  178. package/version.js +10 -8
  179. /package/packages/dd-trace/src/appsec/{blocked_templates.js → blocking/templates.js} +0 -0
@@ -9,6 +9,7 @@ const rrtypes = {
9
9
  resolveAny: 'ANY',
10
10
  resolve4: 'A',
11
11
  resolve6: 'AAAA',
12
+ resolveCaa: 'CAA',
12
13
  resolveCname: 'CNAME',
13
14
  resolveMx: 'MX',
14
15
  resolveNs: 'NS',
@@ -17,6 +18,7 @@ const rrtypes = {
17
18
  resolvePtr: 'PTR',
18
19
  resolveNaptr: 'NAPTR',
19
20
  resolveSoa: 'SOA',
21
+ resolveTlsa: 'TLSA',
20
22
  }
21
23
 
22
24
  // `dns.promises` and `require('dns/promises')` resolve to the same exports object. Both
@@ -81,7 +83,7 @@ function buildCallbackArgsContext (rrtype) {
81
83
  const captured = [...args]
82
84
  captured.pop() // remove the callback
83
85
  if (rrtype) {
84
- captured.push(rrtype)
86
+ insertRrtype(captured, rrtype)
85
87
  }
86
88
  return { args: captured }
87
89
  }
@@ -91,8 +93,25 @@ function buildPromiseArgsContext (rrtype) {
91
93
  return function (_, args) {
92
94
  const captured = [...args]
93
95
  if (rrtype) {
94
- captured.push(rrtype)
96
+ insertRrtype(captured, rrtype)
95
97
  }
96
98
  return { args: captured }
97
99
  }
98
100
  }
101
+
102
+ /**
103
+ * @param {unknown[]} captured
104
+ * @param {string} rrtype
105
+ */
106
+ function insertRrtype (captured, rrtype) {
107
+ if (captured.length === 0) {
108
+ captured.push(rrtype)
109
+ return
110
+ }
111
+
112
+ captured.push(rrtype)
113
+ for (let index = captured.length - 1; index > 1; index--) {
114
+ captured[index] = captured[index - 1]
115
+ }
116
+ captured[1] = rrtype
117
+ }
@@ -149,6 +149,7 @@ function wrapBrowserWindow (electron) {
149
149
 
150
150
  // BrowserWindow doesn't support subclassing because it's all native code
151
151
  // so we return an instance of it instead of the subclass.
152
+ // eslint-disable-next-line no-constructor-return
152
153
  return win
153
154
  }
154
155
  }
@@ -25,6 +25,8 @@ const bodyPublished = new WeakSet()
25
25
  let lastPublishedError
26
26
  let lastPublishedReq
27
27
 
28
+ /** @typedef {{ length: number, [index: number]: unknown } & Iterable<unknown>} ArgumentsLike */
29
+
28
30
  function wrapFastify (fastify, hasParsingEvents) {
29
31
  if (typeof fastify !== 'function') return fastify
30
32
 
@@ -81,7 +83,7 @@ function wrapAddHook (addHook) {
81
83
  * @param {string} name Lifecycle phase the hook was registered against.
82
84
  * @param {Function} fn User-supplied hook.
83
85
  * @param {unknown} thisArg `this` Fastify passes to the hook.
84
- * @param {ArrayLike<unknown>} args Fastify's positional args; the dispatcher always
86
+ * @param {ArgumentsLike} args Fastify's positional args; the dispatcher always
85
87
  * places `done` as the trailing positional (see fastify/lib/hooks.js hookIterator,
86
88
  * onSendHookRunner, preParsingHookRunner, onRequestAbortHookRunner).
87
89
  */
@@ -13,6 +13,8 @@ const errorChannel = channel('apm:grpc:client:request:error')
13
13
  const finishChannel = channel('apm:grpc:client:request:finish')
14
14
  const emitChannel = channel('apm:grpc:client:request:emit')
15
15
 
16
+ /** @typedef {{ length: number, [index: number]: unknown } & Iterable<unknown>} ArgumentsLike */
17
+
16
18
  function createWrapMakeRequest (type, hasPeer = false) {
17
19
  const metadataIndex = type === types.client_stream || type === types.bidi ? 3 : 4
18
20
 
@@ -186,9 +188,9 @@ function callMethod (client, method, args, path, metadata, type, hasPeer = false
186
188
  * one at `index` when the user did not pass their own.
187
189
  *
188
190
  * @param {object} client
189
- * @param {ArrayLike<unknown>} args
191
+ * @param {ArgumentsLike} args
190
192
  * @param {number} index
191
- * @returns {{ metadata: object | undefined, args: ArrayLike<unknown> }}
193
+ * @returns {{ metadata: object | undefined, args: ArgumentsLike }}
192
194
  */
193
195
  function resolveMetadata (client, args, index) {
194
196
  const grpc = client && getGrpc(client)
@@ -3,6 +3,8 @@
3
3
  const shimmer = require('../../../datadog-shimmer')
4
4
  const { channel } = require('./instrument')
5
5
 
6
+ /** @typedef {{ length: number, [index: number]: unknown } & Iterable<unknown>} ArgumentsLike */
7
+
6
8
  /**
7
9
  * Create a shimmer-compatible instrumentor for callback-style APIs whose work is offloaded to the
8
10
  * libuv worker thread pool (e.g. zlib.gzip, crypto.pbkdf2, dns.lookup). Builds a set of three
@@ -22,7 +24,7 @@ const { channel } = require('./instrument')
22
24
  * @param {boolean} [options.captureResult] set `ctx.result` to the callback's first
23
25
  * non-error argument before publishing `:finish`. Plugins that tag spans from the call's
24
26
  * return value (e.g. the DNS lookup plugin) rely on this.
25
- * @returns {(buildContext: (thisArg: unknown, args: IArguments) => object | undefined) =>
27
+ * @returns {(buildContext: (thisArg: unknown, args: ArgumentsLike) => object | undefined) =>
26
28
  * (fn: Function) => Function}
27
29
  */
28
30
  function createCallbackInstrumentor (prefix, { captureResult = false } = {}) {
@@ -59,7 +59,9 @@ module.exports = {
59
59
  '@smithy/smithy-client': () => require('../aws-sdk'),
60
60
  '@vitest/runner': { esmFirst: true, fn: () => require('../vitest') },
61
61
  '@wdio/cli': { esmFirst: true, fn: () => require('../webdriverio') },
62
+ '@wdio/jasmine-framework': { esmFirst: true, fn: () => require('../webdriverio') },
62
63
  '@wdio/local-runner': { esmFirst: true, fn: () => require('../webdriverio') },
64
+ '@wdio/utils': { esmFirst: true, fn: () => require('../webdriverio') },
63
65
  aerospike: () => require('../aerospike'),
64
66
  ai: () => require('../ai'),
65
67
  amqp10: () => require('../amqp10'),
@@ -5,8 +5,9 @@ const { join } = require('path')
5
5
  const { pathToFileURL } = require('url')
6
6
  const log = require('../../../../dd-trace/src/log')
7
7
  const { create } = require('../../../../../vendor/dist/@apm-js-collab/code-transformer')
8
- const { waitForAsyncEnd } = require('./transforms')
9
8
  const instrumentations = require('./instrumentations')
9
+ const { getRewriteTarget } = require('./targets')
10
+ const { waitForAsyncEnd } = require('./transforms')
10
11
 
11
12
  // `dc-polyfill` is referenced from injected `require()` (CJS) and `import`
12
13
  // (ESM) statements that the transformer splices into the rewritten module.
@@ -42,18 +43,23 @@ for (const matcher of [matcherCjs, matcherEsm]) {
42
43
  // eslint-disable-next-line unicorn/no-useless-concat -- Keep the source-map marker non-contiguous.
43
44
  const SOURCE_MAP_PREFIX = '//# sourceMapping' + 'URL=data:application/json;base64,'
44
45
 
45
- function rewrite (content, filename, format) {
46
+ /**
47
+ * @param {string|Buffer|ArrayBuffer|Uint8Array} content
48
+ * @param {string} filename
49
+ * @param {string} [format]
50
+ * @param {{ moduleName: string, filePath: string }} [target]
51
+ * @returns {string|Buffer|ArrayBuffer|Uint8Array}
52
+ */
53
+ function rewrite (content, filename, format, target) {
46
54
  if (!content) return content
47
- if (!filename.includes('node_modules')) return content
55
+
56
+ target ||= getRewriteTarget(filename)
57
+ if (!target) return content
48
58
 
49
59
  filename = filename.replace('file://', '')
50
60
 
51
61
  const moduleType = format === 'module' ? 'esm' : 'cjs'
52
- const [modulePath] = filename.split('/node_modules/').reverse()
53
- const moduleParts = modulePath.split('/')
54
- const splitIndex = moduleParts[0].startsWith('@') ? 2 : 1
55
- const moduleName = moduleParts.slice(0, splitIndex).join('/')
56
- const filePath = moduleParts.slice(splitIndex).join('/')
62
+ const { moduleName, filePath } = target
57
63
  const version = getVersion(filename, filePath)
58
64
 
59
65
  if (disabled.has(moduleName)) return content
@@ -64,8 +70,10 @@ function rewrite (content, filename, format) {
64
70
  if (!transformer) return content
65
71
 
66
72
  try {
73
+ const source = getSourceText(content)
74
+
67
75
  // TODO: pass existing sourcemap as input for remapping
68
- const { code, map } = transformer.transform(content, moduleType)
76
+ const { code, map } = transformer.transform(source, moduleType)
69
77
 
70
78
  if (!map) return code
71
79
 
@@ -79,6 +87,22 @@ function rewrite (content, filename, format) {
79
87
  return content
80
88
  }
81
89
 
90
+ /** @typedef {{ buffer: ArrayBuffer | SharedArrayBuffer, byteLength: number, byteOffset: number }} BufferView */
91
+
92
+ /**
93
+ * Convert the source representations accepted by Node.js loader hooks to text.
94
+ *
95
+ * @param {string | ArrayBuffer | BufferView} source
96
+ * @returns {string}
97
+ */
98
+ function getSourceText (source) {
99
+ if (typeof source === 'string') return source
100
+ if (ArrayBuffer.isView(source)) {
101
+ return Buffer.from(source.buffer, source.byteOffset, source.byteLength).toString('utf8')
102
+ }
103
+ return Buffer.from(source).toString('utf8')
104
+ }
105
+
82
106
  function disable (instrumentation) {
83
107
  disabled.add(instrumentation)
84
108
  }
@@ -54,4 +54,122 @@ module.exports = [
54
54
  channelName: 'LocalRunner_shutdown',
55
55
  transform: 'waitForAsyncEnd',
56
56
  },
57
+ {
58
+ module: {
59
+ name: '@wdio/jasmine-framework',
60
+ versionRange: '>=9.0.0',
61
+ filePath: 'build/index.js',
62
+ },
63
+ functionQuery: {
64
+ className: 'JasmineAdapter',
65
+ methodName: 'init',
66
+ kind: 'Async',
67
+ },
68
+ channelName: 'JasmineAdapter_init',
69
+ },
70
+ {
71
+ module: {
72
+ name: '@wdio/jasmine-framework',
73
+ versionRange: '>=9.0.0',
74
+ filePath: 'build/index.js',
75
+ },
76
+ astQuery: 'VariableDeclarator[id.name="JasmineAdapter"] > ClassExpression > ClassBody > ' +
77
+ 'MethodDefinition[key.name="init"] ReturnStatement > ' +
78
+ 'CallExpression[callee.object.name="promise"][callee.property.name="then"], ' +
79
+ 'ClassDeclaration[id.name="JasmineAdapter"] > ClassBody > MethodDefinition[key.name="init"] ReturnStatement > ' +
80
+ 'CallExpression[callee.object.name="promise"][callee.property.name="then"]',
81
+ channelName: 'JasmineAdapter_init',
82
+ transform: 'waitForAsyncEnd',
83
+ },
84
+ {
85
+ module: {
86
+ name: '@wdio/jasmine-framework',
87
+ versionRange: '>=9.0.0',
88
+ filePath: 'build/index.js',
89
+ },
90
+ functionQuery: {
91
+ className: 'JasmineAdapter',
92
+ methodName: 'run',
93
+ kind: 'Async',
94
+ },
95
+ channelName: 'JasmineAdapter_run',
96
+ },
97
+ {
98
+ module: {
99
+ name: '@wdio/jasmine-framework',
100
+ versionRange: '>=9.0.0',
101
+ filePath: 'build/index.js',
102
+ },
103
+ astQuery: 'VariableDeclarator[id.name="JasmineAdapter"] > ClassExpression > ClassBody > ' +
104
+ 'MethodDefinition[key.name="run"] ReturnStatement > ' +
105
+ 'CallExpression[callee.object.name="promise"][callee.property.name="then"], ' +
106
+ 'ClassDeclaration[id.name="JasmineAdapter"] > ClassBody > MethodDefinition[key.name="run"] ReturnStatement > ' +
107
+ 'CallExpression[callee.object.name="promise"][callee.property.name="then"]',
108
+ channelName: 'JasmineAdapter_run',
109
+ transform: 'waitForAsyncEnd',
110
+ },
111
+ {
112
+ module: {
113
+ name: '@wdio/jasmine-framework',
114
+ versionRange: '>=9.0.0',
115
+ filePath: 'build/index.js',
116
+ },
117
+ functionQuery: {
118
+ className: 'JasmineReporter',
119
+ methodName: 'specDone',
120
+ kind: 'Sync',
121
+ },
122
+ channelName: 'JasmineReporter_specDone',
123
+ },
124
+ {
125
+ module: {
126
+ name: '@wdio/jasmine-framework',
127
+ versionRange: '>=9.0.0',
128
+ filePath: 'build/index.js',
129
+ },
130
+ functionQuery: {
131
+ className: 'JasmineReporter',
132
+ methodName: 'specStarted',
133
+ kind: 'Sync',
134
+ },
135
+ channelName: 'JasmineReporter_specStarted',
136
+ },
137
+ {
138
+ module: {
139
+ name: '@wdio/jasmine-framework',
140
+ versionRange: '>=9.0.0',
141
+ filePath: 'build/index.js',
142
+ },
143
+ functionQuery: {
144
+ className: 'JasmineReporter',
145
+ methodName: 'suiteStarted',
146
+ kind: 'Sync',
147
+ },
148
+ channelName: 'JasmineReporter_suiteStarted',
149
+ },
150
+ {
151
+ module: {
152
+ name: '@wdio/jasmine-framework',
153
+ versionRange: '>=9.0.0',
154
+ filePath: 'build/index.js',
155
+ },
156
+ functionQuery: {
157
+ className: 'JasmineReporter',
158
+ methodName: 'suiteDone',
159
+ kind: 'Sync',
160
+ },
161
+ channelName: 'JasmineReporter_suiteDone',
162
+ },
163
+ {
164
+ module: {
165
+ name: '@wdio/utils',
166
+ versionRange: '>=9.0.0',
167
+ filePath: 'build/index.js',
168
+ },
169
+ functionQuery: {
170
+ expressionName: 'testFrameworkFnWrapper',
171
+ kind: 'Async',
172
+ },
173
+ channelName: 'testFrameworkFnWrapper',
174
+ },
57
175
  ]
@@ -1,4 +1,8 @@
1
- import { rewrite } from './index.js'
1
+ import * as Module from 'module'
2
+
3
+ const require = Module.createRequire(import.meta.url)
4
+ const { getRewriteTarget } = require('./targets.js')
5
+ let rewriter
2
6
 
3
7
  async function load (url, context, nextLoad) {
4
8
  const result = await nextLoad(url, context)
@@ -12,6 +16,11 @@ function loadSync (url, context, nextLoad) {
12
16
  return rewriteResult(result, url, context)
13
17
  }
14
18
 
19
+ /**
20
+ * @param {{ format?: string, source?: unknown }} result
21
+ * @param {string} url
22
+ * @param {{ format?: string }} context
23
+ */
15
24
  function rewriteResult (result, url, context) {
16
25
  const format = result.format || context.format
17
26
 
@@ -19,7 +28,16 @@ function rewriteResult (result, url, context) {
19
28
  // double-instruments CommonJS entrypoints loaded through sync hooks.
20
29
  if (format === 'commonjs') return result
21
30
 
22
- result.source = rewrite(result.source, url, format)
31
+ if (result.source) {
32
+ const target = getRewriteTarget(url)
33
+ if (target) {
34
+ if (!rewriter) {
35
+ rewriter = require('./index.js')
36
+ }
37
+
38
+ result.source = rewriter.rewrite(result.source, url, format, target)
39
+ }
40
+ }
23
41
 
24
42
  return result
25
43
  }
@@ -0,0 +1,32 @@
1
+ 'use strict'
2
+
3
+ // Generated by scripts/generate-rewriter-targets.js from ./instrumentations. Do not edit by hand.
4
+ const targets = require('./targets.json')
5
+
6
+ const NODE_MODULES = '/node_modules/'
7
+
8
+ /**
9
+ * @typedef {object} RewriteTarget
10
+ * @property {string} moduleName
11
+ * @property {string} filePath
12
+ */
13
+
14
+ /**
15
+ * @param {string} filename
16
+ * @returns {RewriteTarget|undefined}
17
+ */
18
+ function getRewriteTarget (filename) {
19
+ const nodeModulesIndex = filename.lastIndexOf(NODE_MODULES)
20
+ if (nodeModulesIndex === -1) return
21
+
22
+ const modulePath = filename.slice(nodeModulesIndex + NODE_MODULES.length)
23
+ const moduleName = targets[modulePath]
24
+ if (typeof moduleName !== 'string') return
25
+
26
+ return {
27
+ moduleName,
28
+ filePath: modulePath.slice(moduleName.length + 1),
29
+ }
30
+ }
31
+
32
+ module.exports = { getRewriteTarget }
@@ -0,0 +1,61 @@
1
+ {
2
+ "@anthropic-ai/claude-agent-sdk/sdk.mjs": "@anthropic-ai/claude-agent-sdk",
3
+ "@aws/durable-execution-sdk-js/dist-cjs/index.js": "@aws/durable-execution-sdk-js",
4
+ "@aws/durable-execution-sdk-js/dist/index.mjs": "@aws/durable-execution-sdk-js",
5
+ "@azure/cosmos/dist/browser/plugins/Plugin.js": "@azure/cosmos",
6
+ "@azure/cosmos/dist/commonjs/plugins/Plugin.js": "@azure/cosmos",
7
+ "@azure/cosmos/dist/esm/plugins/Plugin.js": "@azure/cosmos",
8
+ "@azure/cosmos/dist/react-native/plugins/Plugin.js": "@azure/cosmos",
9
+ "@graphql-tools/executor/cjs/execution/execute.js": "@graphql-tools/executor",
10
+ "@graphql-tools/executor/cjs/execution/normalizedExecutor.js": "@graphql-tools/executor",
11
+ "@graphql-tools/executor/esm/execution/execute.js": "@graphql-tools/executor",
12
+ "@graphql-tools/executor/esm/execution/normalizedExecutor.js": "@graphql-tools/executor",
13
+ "@langchain/core/dist/embeddings.cjs": "@langchain/core",
14
+ "@langchain/core/dist/embeddings.js": "@langchain/core",
15
+ "@langchain/core/dist/language_models/chat_models.cjs": "@langchain/core",
16
+ "@langchain/core/dist/language_models/chat_models.js": "@langchain/core",
17
+ "@langchain/core/dist/language_models/llms.cjs": "@langchain/core",
18
+ "@langchain/core/dist/language_models/llms.js": "@langchain/core",
19
+ "@langchain/core/dist/runnables/base.cjs": "@langchain/core",
20
+ "@langchain/core/dist/runnables/base.js": "@langchain/core",
21
+ "@langchain/core/dist/tools/index.cjs": "@langchain/core",
22
+ "@langchain/core/dist/tools/index.js": "@langchain/core",
23
+ "@langchain/core/dist/vectorstores.cjs": "@langchain/core",
24
+ "@langchain/core/dist/vectorstores.js": "@langchain/core",
25
+ "@langchain/langgraph/dist/pregel/index.cjs": "@langchain/langgraph",
26
+ "@langchain/langgraph/dist/pregel/index.js": "@langchain/langgraph",
27
+ "@modelcontextprotocol/sdk/dist/cjs/client/index.js": "@modelcontextprotocol/sdk",
28
+ "@modelcontextprotocol/sdk/dist/cjs/server/mcp.js": "@modelcontextprotocol/sdk",
29
+ "@modelcontextprotocol/sdk/dist/esm/client/index.js": "@modelcontextprotocol/sdk",
30
+ "@modelcontextprotocol/sdk/dist/esm/server/mcp.js": "@modelcontextprotocol/sdk",
31
+ "@openai/agents-openai/dist/openaiChatCompletionsModel.js": "@openai/agents-openai",
32
+ "@openai/agents-openai/dist/openaiChatCompletionsModel.mjs": "@openai/agents-openai",
33
+ "@wdio/cli/build/index.js": "@wdio/cli",
34
+ "@wdio/jasmine-framework/build/index.js": "@wdio/jasmine-framework",
35
+ "@wdio/local-runner/build/index.js": "@wdio/local-runner",
36
+ "@wdio/utils/build/index.js": "@wdio/utils",
37
+ "ai/dist/index.js": "ai",
38
+ "ai/dist/index.mjs": "ai",
39
+ "bullmq/dist/cjs/classes/flow-producer.js": "bullmq",
40
+ "bullmq/dist/cjs/classes/queue.js": "bullmq",
41
+ "bullmq/dist/cjs/classes/worker.js": "bullmq",
42
+ "bullmq/dist/esm/classes/flow-producer.js": "bullmq",
43
+ "bullmq/dist/esm/classes/queue.js": "bullmq",
44
+ "bullmq/dist/esm/classes/worker.js": "bullmq",
45
+ "graphql/execution/execute.js": "graphql",
46
+ "graphql/execution/execute.mjs": "graphql",
47
+ "graphql/language/parser.js": "graphql",
48
+ "graphql/language/parser.mjs": "graphql",
49
+ "graphql/language/printer.js": "graphql",
50
+ "graphql/language/printer.mjs": "graphql",
51
+ "graphql/language/visitor.js": "graphql",
52
+ "graphql/language/visitor.mjs": "graphql",
53
+ "graphql/utilities/index.js": "graphql",
54
+ "graphql/utilities/index.mjs": "graphql",
55
+ "graphql/validation/validate.js": "graphql",
56
+ "graphql/validation/validate.mjs": "graphql",
57
+ "mercurius/index.js": "mercurius",
58
+ "playwright-core/lib/coreBundle.js": "playwright-core",
59
+ "playwright/lib/index.js": "playwright",
60
+ "playwright/lib/runner/index.js": "playwright"
61
+ }
@@ -7,10 +7,25 @@ const routerMountPaths = new WeakMap() // to track mount paths for router instan
7
7
  const layerMeta = new WeakMap() // per-layer middleware dispatch metadata (resolved name + route matchers)
8
8
  const appMountedRouters = new WeakSet() // to track routers mounted via app.use()
9
9
 
10
+ /**
11
+ * @typedef {object} LayerMeta
12
+ * @property {string} [name]
13
+ * @property {string} [captureRoute]
14
+ * @property {boolean} [needMultiMatch]
15
+ * @property {Array<{ path?: string, regex?: RegExp }> & {
16
+ * hasStarPath?: boolean,
17
+ * hasSlashPath?: boolean
18
+ * }} [matchers]
19
+ */
20
+
10
21
  const METHODS = [...require('http').METHODS.map(v => v.toLowerCase()), 'all']
11
22
 
12
23
  const routeAddedChannel = channel('apm:express:route:added')
13
24
 
25
+ /**
26
+ * @typedef {{ stack?: Array<{ route?: unknown, handle?: ExpressRouter }> }} ExpressRouter
27
+ */
28
+
14
29
  /**
15
30
  * Joins two URL path segments into a single path
16
31
  *
@@ -57,12 +72,14 @@ function collectRoutesFromRouter (router, prefix) {
57
72
  const fullPaths = getRouteFullPaths(route, prefix)
58
73
 
59
74
  for (const fullPath of fullPaths) {
60
- for (const [method, enabled] of Object.entries(route.methods || {})) {
61
- if (!enabled) continue
62
- routeAddedChannel.publish({
63
- method: normalizeMethodName(method),
64
- path: fullPath,
65
- })
75
+ if (route.methods) {
76
+ for (const [method, enabled] of Object.entries(route.methods)) {
77
+ if (!enabled) continue
78
+ routeAddedChannel.publish({
79
+ method: normalizeMethodName(method),
80
+ path: fullPath,
81
+ })
82
+ }
66
83
  }
67
84
  }
68
85
  } else if (layer.handle?.stack?.length) {
@@ -121,10 +138,19 @@ function getRouterMountPaths (router) {
121
138
  return [...paths]
122
139
  }
123
140
 
141
+ /**
142
+ * @param {object} layer
143
+ * @param {LayerMeta} meta
144
+ * @returns {void}
145
+ */
124
146
  function setLayerMeta (layer, meta) {
125
147
  layerMeta.set(layer, meta)
126
148
  }
127
149
 
150
+ /**
151
+ * @param {object} layer
152
+ * @returns {LayerMeta | undefined}
153
+ */
128
154
  function getLayerMeta (layer) {
129
155
  return layerMeta.get(layer)
130
156
  }
@@ -157,6 +183,8 @@ function isAppMounted (router) {
157
183
  * Express accepts strings, regex, arrays (possibly nested), or
158
184
  * no mount path at all; this helper returns the flattened set of paths along
159
185
  * with the index where actual middleware arguments start.
186
+ *
187
+ * @param {unknown} path First `use()` argument, which may be a mount path or already a middleware.
160
188
  */
161
189
  function extractMountPaths (path) {
162
190
  const hasMount = typeof path === 'string' || path instanceof RegExp || Array.isArray(path)
@@ -174,6 +202,9 @@ function extractMountPaths (path) {
174
202
 
175
203
  /**
176
204
  * Detect cycle router graphs.
205
+ *
206
+ * @param {ExpressRouter | undefined} router
207
+ * @param {Set<ExpressRouter>} [stack]
177
208
  */
178
209
  function hasRouterCycle (router, stack = new Set()) {
179
210
  if (!router?.stack?.length) return false
@@ -14,7 +14,7 @@ const TRANSFORM_OPTIONS = {
14
14
 
15
15
  function getCoverageBackfillFiles (skippableSuitesCoverage, rootDir, getTestSuitePath) {
16
16
  const files = []
17
- for (const filename of Object.keys(skippableSuitesCoverage || {})) {
17
+ for (const filename of Object.keys(skippableSuitesCoverage)) {
18
18
  const relativeFilename = path.isAbsolute(filename)
19
19
  ? getTestSuitePath(filename, rootDir)
20
20
  : filename