dd-trace 6.13.0 → 6.15.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 (208) hide show
  1. package/LICENSE-3rdparty.csv +3 -1
  2. package/ci/init.js +8 -3
  3. package/ci/test-optimization-validation/ci-package-scripts.js +2 -2
  4. package/ci/test-optimization-validation/ci-remediation.js +6 -6
  5. package/ci/test-optimization-validation/command-blocker.js +7 -5
  6. package/ci/test-optimization-validation/framework-adapters/cucumber.js +1 -1
  7. package/ci/test-optimization-validation/framework-adapters/vitest.js +3 -3
  8. package/ci/test-optimization-validation/package-check.js +1 -1
  9. package/ci/test-optimization-validation/report-writer.js +7 -5
  10. package/ci/vitest-no-worker-init-runner-setup.mjs +8 -0
  11. package/ci/vitest-no-worker-init-setup.mjs +13 -13
  12. package/ci/vitest-no-worker-init-v5-setup.mjs +4 -0
  13. package/index.d.ts +8 -0
  14. package/package.json +13 -10
  15. package/packages/datadog-esbuild/index.js +3 -1
  16. package/packages/datadog-instrumentations/src/cypress-config.js +19 -17
  17. package/packages/datadog-instrumentations/src/fs.js +24 -20
  18. package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -2
  19. package/packages/datadog-instrumentations/src/graphql.js +16 -16
  20. package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +504 -0
  21. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  22. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +265 -0
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +1 -2
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +95 -30
  25. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +0 -25
  26. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +83 -0
  27. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +85 -1
  28. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  29. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/mercurius.js +30 -12
  30. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +14 -5
  31. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +251 -0
  32. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +11 -1
  33. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +562 -27
  34. package/packages/datadog-instrumentations/src/jest.js +166 -45
  35. package/packages/datadog-instrumentations/src/knex.js +76 -0
  36. package/packages/datadog-instrumentations/src/mariadb.js +6 -0
  37. package/packages/datadog-instrumentations/src/mocha/common.js +59 -2
  38. package/packages/datadog-instrumentations/src/mocha/main.js +66 -20
  39. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
  40. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +98 -0
  41. package/packages/datadog-instrumentations/src/mocha/worker.js +12 -8
  42. package/packages/datadog-instrumentations/src/net.js +14 -17
  43. package/packages/datadog-instrumentations/src/next.js +212 -62
  44. package/packages/datadog-instrumentations/src/openai.js +42 -40
  45. package/packages/datadog-instrumentations/src/pg.js +15 -0
  46. package/packages/datadog-instrumentations/src/playwright.js +113 -13
  47. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +40 -0
  48. package/packages/datadog-instrumentations/src/sequelize.js +94 -2
  49. package/packages/datadog-instrumentations/src/undici.js +53 -4
  50. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +37 -3
  51. package/packages/datadog-instrumentations/src/vitest-main.js +92 -9
  52. package/packages/datadog-instrumentations/src/vitest-worker.js +71 -14
  53. package/packages/datadog-instrumentations/src/webdriverio.js +965 -6
  54. package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
  55. package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
  56. package/packages/datadog-plugin-amqp10/src/util.js +2 -1
  57. package/packages/datadog-plugin-avsc/src/schema_iterator.js +6 -1
  58. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +16 -5
  59. package/packages/datadog-plugin-cassandra-driver/src/index.js +8 -3
  60. package/packages/datadog-plugin-cucumber/src/index.js +0 -2
  61. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +262 -48
  62. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -1
  63. package/packages/datadog-plugin-graphql/src/execute.js +998 -196
  64. package/packages/datadog-plugin-graphql/src/index.js +27 -7
  65. package/packages/datadog-plugin-graphql/src/jit.js +136 -0
  66. package/packages/datadog-plugin-graphql/src/request.js +18 -27
  67. package/packages/datadog-plugin-graphql/src/resolve-error.js +108 -0
  68. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -2
  69. package/packages/datadog-plugin-graphql/src/tools/transforms.js +45 -3
  70. package/packages/datadog-plugin-graphql/src/utils.js +208 -120
  71. package/packages/datadog-plugin-graphql/src/validate.js +10 -23
  72. package/packages/datadog-plugin-jest/src/index.js +0 -6
  73. package/packages/datadog-plugin-langchain/src/tracing.js +7 -0
  74. package/packages/datadog-plugin-mocha/src/index.js +403 -75
  75. package/packages/datadog-plugin-mongodb-core/src/query.js +6 -0
  76. package/packages/datadog-plugin-mysql/src/index.js +41 -15
  77. package/packages/datadog-plugin-net/src/tcp.js +3 -1
  78. package/packages/datadog-plugin-next/src/index.js +63 -29
  79. package/packages/datadog-plugin-playwright/src/index.js +167 -27
  80. package/packages/datadog-plugin-undici/src/index.js +27 -41
  81. package/packages/datadog-plugin-vitest/src/index.js +6 -12
  82. package/packages/dd-trace/src/aiguard/evaluation.js +2 -1
  83. package/packages/dd-trace/src/aiguard/messages/anthropic.js +8 -1
  84. package/packages/dd-trace/src/aiguard/messages/openai.js +8 -1
  85. package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +20 -6
  86. package/packages/dd-trace/src/appsec/api_security/index.js +23 -6
  87. package/packages/dd-trace/src/appsec/api_security/sampler.js +99 -40
  88. package/packages/dd-trace/src/appsec/graphql.js +6 -2
  89. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
  90. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -1
  91. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +8 -2
  92. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +3 -1
  93. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +531 -95
  94. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +1 -1
  95. package/packages/dd-trace/src/appsec/lambda.js +44 -26
  96. package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +32 -2
  97. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +8 -8
  98. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +6 -4
  99. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +20 -4
  100. package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +5 -173
  101. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +7 -6
  102. package/packages/dd-trace/src/ci-visibility/exporters/agents.js +54 -0
  103. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +1 -2
  104. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +394 -225
  105. package/packages/dd-trace/src/ci-visibility/exporters/limits.js +9 -0
  106. package/packages/dd-trace/src/ci-visibility/exporters/request.js +323 -31
  107. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +42 -0
  108. package/packages/dd-trace/src/ci-visibility/final-flush.js +2 -1
  109. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +57 -18
  110. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +0 -3
  111. package/packages/dd-trace/src/ci-visibility/requests/request.js +11 -0
  112. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +164 -71
  113. package/packages/dd-trace/src/ci-visibility/requests/video-request.js +180 -0
  114. package/packages/dd-trace/src/ci-visibility/telemetry.js +10 -7
  115. package/packages/dd-trace/src/ci-visibility/test-video.js +61 -0
  116. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -0
  117. package/packages/dd-trace/src/config/index.js +73 -13
  118. package/packages/dd-trace/src/config/parsers.js +11 -1
  119. package/packages/dd-trace/src/config/stable.js +3 -3
  120. package/packages/dd-trace/src/config/supported-configurations.json +22 -2
  121. package/packages/dd-trace/src/crashtracking/crashtracker.js +82 -18
  122. package/packages/dd-trace/src/debugger/config.js +12 -1
  123. package/packages/dd-trace/src/debugger/constants.js +1 -0
  124. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -1
  125. package/packages/dd-trace/src/debugger/devtools_client/request-options.js +28 -0
  126. package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -40
  127. package/packages/dd-trace/src/debugger/devtools_client/status.js +11 -6
  128. package/packages/dd-trace/src/debugger/devtools_client/tags.js +41 -0
  129. package/packages/dd-trace/src/debugger/index.js +23 -3
  130. package/packages/dd-trace/src/dogstatsd.js +510 -76
  131. package/packages/dd-trace/src/encode/0.4-cross-payload.js +170 -0
  132. package/packages/dd-trace/src/encode/0.4.js +5 -5
  133. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -8
  134. package/packages/dd-trace/src/evp_proxy/direct.js +3 -25
  135. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  136. package/packages/dd-trace/src/exporters/agent/writer.js +24 -7
  137. package/packages/dd-trace/src/exporters/agentless/index.js +7 -9
  138. package/packages/dd-trace/src/exporters/agentless/writer.js +103 -119
  139. package/packages/dd-trace/src/exporters/common/agents.js +28 -6
  140. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -2
  141. package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +191 -0
  142. package/packages/dd-trace/src/exporters/common/proxy.js +52 -0
  143. package/packages/dd-trace/src/exporters/common/request.js +42 -14
  144. package/packages/dd-trace/src/exporters/common/url.js +40 -1
  145. package/packages/dd-trace/src/exporters/common/writer.js +9 -7
  146. package/packages/dd-trace/src/flush.js +6 -3
  147. package/packages/dd-trace/src/id.js +14 -0
  148. package/packages/dd-trace/src/index.js +5 -2
  149. package/packages/dd-trace/src/llmobs/experiments/dataset.js +2 -1
  150. package/packages/dd-trace/src/llmobs/index.js +32 -32
  151. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +22 -71
  152. package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +23 -13
  153. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +7 -0
  154. package/packages/dd-trace/src/llmobs/util.js +0 -33
  155. package/packages/dd-trace/src/llmobs/writers/base.js +49 -32
  156. package/packages/dd-trace/src/log/index.js +7 -1
  157. package/packages/dd-trace/src/{ci-visibility/log-submission → log-submission}/log-submission-plugin.js +48 -19
  158. package/packages/dd-trace/src/openfeature/writers/base.js +14 -12
  159. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  160. package/packages/dd-trace/src/opentelemetry/logs/index.js +5 -24
  161. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +14 -4
  162. package/packages/dd-trace/src/opentelemetry/metrics/index.js +15 -22
  163. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +14 -4
  164. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +10 -0
  165. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +5 -0
  166. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +19 -4
  167. package/packages/dd-trace/src/opentelemetry/resource-attributes.js +55 -0
  168. package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
  169. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +10 -0
  170. package/packages/dd-trace/src/opentracing/propagation/text_map.js +101 -20
  171. package/packages/dd-trace/src/payload-tagging/index.js +2 -1
  172. package/packages/dd-trace/src/plugins/ci_plugin.js +1 -6
  173. package/packages/dd-trace/src/plugins/tracing.js +12 -10
  174. package/packages/dd-trace/src/plugins/util/ci.js +3 -1
  175. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +16 -15
  176. package/packages/dd-trace/src/plugins/util/test.js +83 -20
  177. package/packages/dd-trace/src/plugins/util/url.js +2 -2
  178. package/packages/dd-trace/src/plugins/util/web.js +4 -9
  179. package/packages/dd-trace/src/priority_sampler.js +4 -0
  180. package/packages/dd-trace/src/profiling/config.js +1 -0
  181. package/packages/dd-trace/src/profiling/oom.js +7 -2
  182. package/packages/dd-trace/src/profiling/profiler.js +23 -13
  183. package/packages/dd-trace/src/profiling/profilers/space.js +38 -11
  184. package/packages/dd-trace/src/profiling/webspan-utils.js +7 -4
  185. package/packages/dd-trace/src/proxy.js +75 -5
  186. package/packages/dd-trace/src/remote_config/index.js +319 -101
  187. package/packages/dd-trace/src/remote_config/scheduler.js +37 -12
  188. package/packages/dd-trace/src/runtime_metrics/client.js +37 -8
  189. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +5 -1
  190. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -1
  191. package/packages/dd-trace/src/sampling_rule.js +39 -10
  192. package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +4 -8
  193. package/packages/dd-trace/src/serverless/vercel.js +53 -20
  194. package/packages/dd-trace/src/serverless.js +10 -3
  195. package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
  196. package/packages/dd-trace/src/span_processor.js +18 -3
  197. package/packages/dd-trace/src/span_stats.js +24 -28
  198. package/packages/dd-trace/src/startup-log.js +3 -2
  199. package/packages/dd-trace/src/telemetry/agentless-url.js +28 -0
  200. package/packages/dd-trace/src/telemetry/send-data.js +23 -20
  201. package/packages/dd-trace/src/telemetry/session-propagation.js +3 -2
  202. package/packages/dd-trace/src/tracer.js +4 -5
  203. package/packages/dd-trace/src/tracer_metadata.js +11 -3
  204. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  205. package/vendor/dist/protobufjs/index.js +1 -1
  206. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  207. package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +0 -27
  208. package/packages/dd-trace/src/encode/agentless-json.js +0 -210
@@ -19,6 +19,9 @@ const { performance } = require('node:perf_hooks')
19
19
  * @typedef {{ deferred: boolean }} PoolWaitTransfer
20
20
  * @typedef {{ transfer: PoolWaitTransfer, waitTime: number }} DeferredPoolWait
21
21
  * @typedef {{ pending: boolean, pool: object }} DeferredPoolQueryAcquire
22
+ * @typedef {'mariadb'|'mysql'|'mysql2'|'pg'} DatabaseDriver
23
+ * @typedef {{ connection?: object, owner: object, pending: boolean }} PromisePoolQueryAcquire
24
+ * @typedef {{ waitTime?: number }} PoolAcquireCapture
22
25
  * @typedef {{
23
26
  * connectionFinishCh: Channel,
24
27
  * acquireStartCh: Channel,
@@ -41,6 +44,12 @@ let currentPoolQueryAcquire
41
44
  /** @type {import('node:async_hooks').AsyncLocalStorage<DeferredPoolQueryAcquire>|undefined} */
42
45
  let deferredPoolQueryAcquireStorage
43
46
 
47
+ /** @type {import('node:async_hooks').AsyncLocalStorage<PromisePoolQueryAcquire>|undefined} */
48
+ let promisePoolQueryAcquireStorage
49
+
50
+ /** @type {PoolAcquireCapture|undefined} */
51
+ let currentPoolAcquireCapture
52
+
44
53
  /** @type {WeakMap<object, ClusterAcquire>} */
45
54
  const deferredClusterAcquires = new WeakMap()
46
55
 
@@ -52,6 +61,110 @@ const poolWaitTimes = []
52
61
  const deferredPoolWaitTimes = new WeakMap()
53
62
  let deferredPoolWaitCount = 0
54
63
 
64
+ /** @type {Record<string, { acquireStartCh: Channel, acquireFinishCh: Channel }>} */
65
+ const promisePoolAcquireChannels = {}
66
+
67
+ /** @type {WeakMap<object, Record<string, unknown>>} */
68
+ const promisePoolConnectionConfigs = new WeakMap()
69
+
70
+ const deferredPromisePoolWaitTransfer = { deferred: true }
71
+
72
+ /**
73
+ * Mark a promise-returning ORM operation as the owner of its next pool acquisition.
74
+ *
75
+ * @param {Function} method
76
+ * @param {(receiver: object, args: ArgumentsLike) => object|undefined} resolveOwner
77
+ * @param {(receiver: object, args: ArgumentsLike) => DatabaseDriver|undefined} resolveDriver
78
+ * @returns {Function}
79
+ */
80
+ function wrapPromisePoolQueryMethod (method, resolveOwner, resolveDriver) {
81
+ return function () {
82
+ const driver = resolveDriver(this, arguments)
83
+ if (driver === undefined || !getPromisePoolAcquireChannels(driver).acquireStartCh.hasSubscribers) {
84
+ return method.apply(this, arguments)
85
+ }
86
+
87
+ const owner = resolveOwner(this, arguments)
88
+ if (owner === undefined) return method.apply(this, arguments)
89
+
90
+ const storage = getPromisePoolQueryAcquireStorage()
91
+ return storage.run({ owner, pending: true }, () => method.apply(this, arguments))
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Instrument a promise-returning ORM pool acquisition using the underlying driver contract.
97
+ *
98
+ * @param {Function} method
99
+ * @param {(receiver: object, args: ArgumentsLike) => DatabaseDriver|undefined} resolveDriver
100
+ * @param {(receiver: object, args: ArgumentsLike) => Record<string, unknown>} resolveConfig
101
+ * @param {(receiver: object, args: ArgumentsLike) => boolean} hasIdleConnection
102
+ * @returns {Function}
103
+ */
104
+ function wrapPromisePoolAcquire (method, resolveDriver, resolveConfig, hasIdleConnection) {
105
+ return function () {
106
+ const driver = resolveDriver(this, arguments)
107
+ if (driver === undefined) return method.apply(this, arguments)
108
+
109
+ const channels = getPromisePoolAcquireChannels(driver)
110
+ if (!channels.acquireStartCh.hasSubscribers) return method.apply(this, arguments)
111
+
112
+ const queryAcquire = promisePoolQueryAcquireStorage?.getStore()
113
+ const internal = queryAcquire?.owner === this && queryAcquire.pending
114
+ if (internal) queryAcquire.pending = false
115
+ const start = hasIdleConnection(this, arguments) ? undefined : performance.now()
116
+ const capture = {}
117
+ let ctx
118
+
119
+ if (!internal) {
120
+ ctx = createPromisePoolAcquireContext(driver, resolveConfig(this, arguments))
121
+ channels.acquireStartCh.publish(ctx)
122
+ }
123
+
124
+ let result
125
+ try {
126
+ result = runWithPoolAcquireCapture(capture, method, this, arguments)
127
+ } catch (error) {
128
+ if (internal) queryAcquire.pending = true
129
+ finishPromisePoolAcquire(driver, channels, ctx, start, capture, error, resolveConfig(this, arguments))
130
+ throw error
131
+ }
132
+
133
+ return result.then(connection => {
134
+ const waitTime = capture.waitTime ?? acquireWait(start)
135
+ if (internal) {
136
+ queryAcquire.connection = connection
137
+ setPoolWaitTime(connection, waitTime)
138
+ } else {
139
+ finishPromisePoolAcquireContext(driver, channels, ctx, connection, waitTime)
140
+ }
141
+ return connection
142
+ }, error => {
143
+ if (internal) queryAcquire.pending = true
144
+ finishPromisePoolAcquire(driver, channels, ctx, start, capture, error, resolveConfig(this, arguments))
145
+ throw error
146
+ })
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Clear an acquisition that was never consumed by a driver query.
152
+ *
153
+ * @param {Function} method
154
+ * @returns {Function}
155
+ */
156
+ function wrapPoolRelease (method) {
157
+ return function (connection) {
158
+ const queryAcquire = promisePoolQueryAcquireStorage?.getStore()
159
+ if (queryAcquire?.owner === this && queryAcquire.connection === connection) {
160
+ queryAcquire.connection = undefined
161
+ queryAcquire.pending = true
162
+ }
163
+ if (connection !== undefined) clearPoolWaitTime(connection)
164
+ return method.apply(this, arguments)
165
+ }
166
+ }
167
+
55
168
  /**
56
169
  * @param {Function} method
57
170
  * @param {Channel} connectionStartCh
@@ -194,6 +307,25 @@ function wrapSynchronousPoolGetConnection (getConnection, channels) {
194
307
 
195
308
  const pool = this
196
309
  const ctx = {}
310
+ const capture = currentPoolAcquireCapture
311
+ if (capture !== undefined) {
312
+ const start = acquireStart(pool)
313
+
314
+ arguments[0] = function () {
315
+ capture.waitTime = acquireWait(start)
316
+ return connectionFinishCh.runStores(ctx, callback, this, ...arguments)
317
+ }
318
+ if (queuedCallbacks !== undefined) queuedCallbacks.add(arguments[0])
319
+
320
+ connectionStartCh.publish(ctx)
321
+ try {
322
+ return getConnection.apply(pool, arguments)
323
+ } catch (error) {
324
+ capture.waitTime = acquireWait(start)
325
+ throw error
326
+ }
327
+ }
328
+
197
329
  const acquire = currentPoolQueryAcquire
198
330
  const acquireCtx = acquire === undefined && acquireStartCh.hasSubscribers
199
331
  ? { conf: pool.config.connectionConfig }
@@ -325,6 +457,123 @@ function getDeferredPoolQueryAcquireStorage () {
325
457
  return deferredPoolQueryAcquireStorage
326
458
  }
327
459
 
460
+ /**
461
+ * @returns {import('node:async_hooks').AsyncLocalStorage<PromisePoolQueryAcquire>}
462
+ */
463
+ function getPromisePoolQueryAcquireStorage () {
464
+ if (promisePoolQueryAcquireStorage === undefined) {
465
+ const { AsyncLocalStorage } = require('node:async_hooks')
466
+ promisePoolQueryAcquireStorage = new AsyncLocalStorage()
467
+ }
468
+ return promisePoolQueryAcquireStorage
469
+ }
470
+
471
+ /**
472
+ * @param {DatabaseDriver} driver
473
+ * @returns {{ acquireStartCh: Channel, acquireFinishCh: Channel }}
474
+ */
475
+ function getPromisePoolAcquireChannels (driver) {
476
+ let channels = promisePoolAcquireChannels[driver]
477
+ if (channels === undefined) {
478
+ const { channel } = require('./instrument')
479
+ channels = {
480
+ acquireStartCh: channel(`apm:${driver}:pool:acquire:start`),
481
+ acquireFinishCh: channel(`apm:${driver}:pool:acquire:finish`),
482
+ }
483
+ promisePoolAcquireChannels[driver] = channels
484
+ }
485
+ return channels
486
+ }
487
+
488
+ /**
489
+ * @param {DatabaseDriver} driver
490
+ * @param {Record<string, unknown>} config
491
+ * @returns {Record<string, unknown>}
492
+ */
493
+ function createPromisePoolAcquireContext (driver, config) {
494
+ return driver === 'pg' ? { poolOptions: config } : { conf: config }
495
+ }
496
+
497
+ /**
498
+ * @param {DatabaseDriver} driver
499
+ * @param {{ acquireFinishCh: Channel }} channels
500
+ * @param {Record<string, unknown>|undefined} ctx
501
+ * @param {{
502
+ * config?: Record<string, unknown>,
503
+ * connectionParameters?: Record<string, unknown>,
504
+ * opts?: Record<string, unknown>
505
+ * }} connection
506
+ * @param {number} waitTime
507
+ */
508
+ function finishPromisePoolAcquireContext (driver, channels, ctx, connection, waitTime) {
509
+ ctx.poolWaitTime = waitTime
510
+ if (driver === 'pg') ctx.params = connection.connectionParameters
511
+ else if (driver === 'mariadb') ctx.connectionConfig = promisePoolConnectionConfigs.get(connection)
512
+ else ctx.connectionConfig = connection.config
513
+ channels.acquireFinishCh.publish(ctx)
514
+ }
515
+
516
+ /**
517
+ * @param {object} connection
518
+ * @param {Record<string, unknown>} config
519
+ */
520
+ function setPromisePoolConnectionConfig (connection, config) {
521
+ promisePoolConnectionConfigs.set(connection, config)
522
+ }
523
+
524
+ /**
525
+ * @param {DatabaseDriver} driver
526
+ * @param {{ acquireStartCh: Channel, acquireFinishCh: Channel }} channels
527
+ * @param {Record<string, unknown>|undefined} ctx
528
+ * @param {number|undefined} start
529
+ * @param {PoolAcquireCapture} capture
530
+ * @param {unknown} error
531
+ * @param {Record<string, unknown>} config
532
+ */
533
+ function finishPromisePoolAcquire (driver, channels, ctx, start, capture, error, config) {
534
+ const waitTime = capture.waitTime ?? acquireWait(start)
535
+ if (ctx === undefined) {
536
+ ctx = createPromisePoolAcquireContext(driver, config)
537
+ if (start !== undefined) ctx.startTime = performance.timeOrigin + start
538
+ channels.acquireStartCh.publish(ctx)
539
+ }
540
+ ctx.error = error
541
+ ctx.poolWaitTime = waitTime
542
+ channels.acquireFinishCh.publish(ctx)
543
+ }
544
+
545
+ /**
546
+ * @param {PoolAcquireCapture} capture
547
+ * @param {Function} method
548
+ * @param {object} receiver
549
+ * @param {ArgumentsLike} args
550
+ * @returns {unknown}
551
+ */
552
+ function runWithPoolAcquireCapture (capture, method, receiver, args) {
553
+ const previous = currentPoolAcquireCapture
554
+ currentPoolAcquireCapture = capture
555
+ try {
556
+ return method.apply(receiver, args)
557
+ } finally {
558
+ currentPoolAcquireCapture = previous
559
+ }
560
+ }
561
+
562
+ /**
563
+ * @returns {PoolAcquireCapture|undefined}
564
+ */
565
+ function getPoolAcquireCapture () {
566
+ return currentPoolAcquireCapture
567
+ }
568
+
569
+ /**
570
+ * @param {PoolAcquireCapture} capture
571
+ * @param {number} waitTime
572
+ */
573
+ function setPoolAcquireCaptureWaitTime (capture, waitTime) {
574
+ capture.waitTime = waitTime
575
+ }
576
+
328
577
  /**
329
578
  * @param {Function} method
330
579
  * @param {Record<string, unknown>} receiver
@@ -436,6 +685,15 @@ function clearPoolWaitTime (connection) {
436
685
  if (deferredPoolWaitCount !== 0 && deferredPoolWaitTimes.delete(connection)) deferredPoolWaitCount--
437
686
  }
438
687
 
688
+ /**
689
+ * @param {object} connection
690
+ * @param {number} waitTime
691
+ */
692
+ function setPoolWaitTime (connection, waitTime) {
693
+ clearPoolWaitTime(connection)
694
+ deferPoolWaitTime(deferredPromisePoolWaitTransfer, connection, waitTime)
695
+ }
696
+
439
697
  /**
440
698
  * @param {PoolWaitTransfer} transfer
441
699
  * @param {object} connection
@@ -620,11 +878,15 @@ module.exports = {
620
878
  acquireWait,
621
879
  clearPoolWaitTime,
622
880
  dispatchesAcquireSynchronously,
881
+ getPoolAcquireCapture,
623
882
  isPoolQueryAcquire,
624
883
  reportPoolAcquireError,
625
884
  runOutsidePoolQueryAcquire,
626
885
  runPoolAcquireError,
627
886
  runWithPoolWait,
887
+ setPoolAcquireCaptureWaitTime,
888
+ setPoolWaitTime,
889
+ setPromisePoolConnectionConfig,
628
890
  takePoolWaitTime,
629
891
  wrapPoolAcquireCarrier,
630
892
  wrapPoolClusterGetConnection,
@@ -632,4 +894,7 @@ module.exports = {
632
894
  wrapPoolClusterQueryMethod,
633
895
  wrapPoolGetConnection,
634
896
  wrapPoolQueryMethod,
897
+ wrapPoolRelease,
898
+ wrapPromisePoolAcquire,
899
+ wrapPromisePoolQueryMethod,
635
900
  }
@@ -16,8 +16,7 @@ const runtimeRequire = typeof __webpack_require__ === 'function' ? __non_webpack
16
16
  const compiler = {
17
17
  parse: (sourceText, options) => {
18
18
  try {
19
- // TODO: Figure out ESBuild `createRequire` issue and remove this hack.
20
- const oxc = runtimeRequire(['oxc', 'parser'].join('-'))
19
+ const oxc = runtimeRequire('oxc-parser')
21
20
 
22
21
  compiler.parse = (sourceText, { range, isModule } = {}) => {
23
22
  const { program, errors } = oxc.parseSync('index.js', sourceText, {
@@ -4,40 +4,32 @@ const { readFileSync } = require('fs')
4
4
  const { join } = require('path')
5
5
  const { pathToFileURL } = require('url')
6
6
  const log = require('../../../../dd-trace/src/log')
7
- const { create } = require('../../../../../vendor/dist/@apm-js-collab/code-transformer')
8
7
  const instrumentations = require('./instrumentations')
9
8
  const { getRewriteTarget } = require('./targets')
10
- const { awaitContextCallback, waitForAsyncEnd } = require('./transforms')
11
-
12
- // `dc-polyfill` is referenced from injected `require()` (CJS) and `import`
13
- // (ESM) statements that the transformer splices into the rewritten module.
14
- // `require()` accepts an absolute filesystem path; the ESM resolver rejects it
15
- // with `ERR_INVALID_MODULE_SPECIFIER` and needs a `file://` URL instead. We
16
- // pre-compute both forms here so each matcher hands the transformer a
17
- // specifier that is valid for the module type it is rewriting.
18
- let dcPolyfillCjs
19
- let dcPolyfillEsm
20
-
21
- try {
22
- const resolved = require.resolve('dc-polyfill')
23
- dcPolyfillCjs = resolved.replaceAll('\\', '/')
24
- dcPolyfillEsm = pathToFileURL(resolved).href
25
- } catch {
26
- // The `dc-polyfill` module is unavailable for some reason (like bundling).
27
- // Let's just keep the default of using `diagnostics-channel` as a fallback
28
- // which works for most Node versions.
29
- }
30
9
 
31
- /** @type {Record<string, string>} map of module base name to version */
10
+ /**
11
+ * @typedef {object} InstrumentationMatcher
12
+ * @property {(name: string, transform: Function) => void} addTransform
13
+ * @property {(moduleName: string, version: string|undefined, filePath: string) => Transformer|undefined} getTransformer
14
+ *
15
+ * @typedef {object} Transformer
16
+ * @property {(source: string, moduleType: 'cjs'|'esm') => { code: string, map?: string }} transform
17
+ */
18
+
19
+ /**
20
+ * @type {Record<string, string>} map of module base name to version
21
+ */
32
22
  const moduleVersions = {}
33
23
  const disabled = new Set()
34
- const matcherCjs = create(instrumentations, dcPolyfillCjs)
35
- const matcherEsm = create(instrumentations, dcPolyfillEsm)
36
24
 
37
- for (const matcher of [matcherCjs, matcherEsm]) {
38
- matcher.addTransform('awaitContextCallback', awaitContextCallback)
39
- matcher.addTransform('waitForAsyncEnd', waitForAsyncEnd)
40
- }
25
+ // Matchers are built on the first module that actually needs rewriting. The
26
+ // vendored transformer is a quarter megabyte of bundle that an application
27
+ // without a rewrite target never needs to parse, and an application that loads
28
+ // targets of only one module type never needs the other matcher.
29
+ /** @type {InstrumentationMatcher|undefined} */
30
+ let matcherCjs
31
+ /** @type {InstrumentationMatcher|undefined} */
32
+ let matcherEsm
41
33
 
42
34
  // Keep the marker split: source-map scanners can read a contiguous token in
43
35
  // string literals as this file's own inline map.
@@ -65,8 +57,7 @@ function rewrite (content, filename, format, target) {
65
57
 
66
58
  if (disabled.has(moduleName)) return content
67
59
 
68
- const matcher = moduleType === 'esm' ? matcherEsm : matcherCjs
69
- const transformer = matcher.getTransformer(moduleName, version, filePath)
60
+ const transformer = getMatcher(moduleType).getTransformer(moduleName, version, filePath)
70
61
 
71
62
  if (!transformer) return content
72
63
 
@@ -88,6 +79,80 @@ function rewrite (content, filename, format, target) {
88
79
  return content
89
80
  }
90
81
 
82
+ /**
83
+ * @param {'cjs'|'esm'} moduleType
84
+ * @returns {InstrumentationMatcher}
85
+ */
86
+ function getMatcher (moduleType) {
87
+ if (moduleType === 'esm') {
88
+ matcherEsm ??= createMatcher(moduleType)
89
+
90
+ return matcherEsm
91
+ }
92
+
93
+ matcherCjs ??= createMatcher(moduleType)
94
+
95
+ return matcherCjs
96
+ }
97
+
98
+ /**
99
+ * @param {'cjs'|'esm'} moduleType
100
+ * @returns {InstrumentationMatcher}
101
+ */
102
+ function createMatcher (moduleType) {
103
+ const { create } = require('../../../../../vendor/dist/@apm-js-collab/code-transformer')
104
+ const {
105
+ awaitContextCallback,
106
+ awaitContextCallbackAtFunctionStart,
107
+ awaitContextCallbackAtTryStart,
108
+ configureGraphqlFastPath,
109
+ configureGraphqlJitCompileObject,
110
+ configureGraphqlJitDeferredField,
111
+ configureGraphqlJitExecute,
112
+ configureGraphqlJitRuntime,
113
+ configureMercuriusRequest,
114
+ waitForAsyncEnd,
115
+ } = require('./transforms')
116
+
117
+ const matcher = create(instrumentations, getDcPolyfillSpecifier(moduleType))
118
+
119
+ matcher.addTransform('awaitContextCallback', awaitContextCallback)
120
+ matcher.addTransform('awaitContextCallbackAtFunctionStart', awaitContextCallbackAtFunctionStart)
121
+ matcher.addTransform('awaitContextCallbackAtTryStart', awaitContextCallbackAtTryStart)
122
+ matcher.addTransform('waitForAsyncEnd', waitForAsyncEnd)
123
+ matcher.addTransform('configureGraphqlFastPath', configureGraphqlFastPath)
124
+ matcher.addTransform('configureGraphqlJitCompileObject', configureGraphqlJitCompileObject)
125
+ matcher.addTransform('configureGraphqlJitDeferredField', configureGraphqlJitDeferredField)
126
+ matcher.addTransform('configureGraphqlJitExecute', configureGraphqlJitExecute)
127
+ matcher.addTransform('configureGraphqlJitRuntime', configureGraphqlJitRuntime)
128
+ matcher.addTransform('configureMercuriusRequest', configureMercuriusRequest)
129
+
130
+ return matcher
131
+ }
132
+
133
+ /**
134
+ * `dc-polyfill` is referenced from injected `require()` (CJS) and `import`
135
+ * (ESM) statements that the transformer splices into the rewritten module.
136
+ * `require()` accepts an absolute filesystem path; the ESM resolver rejects it
137
+ * with `ERR_INVALID_MODULE_SPECIFIER` and needs a `file://` URL instead. Each
138
+ * matcher therefore hands the transformer the form that is valid for the
139
+ * module type it is rewriting.
140
+ *
141
+ * @param {'cjs'|'esm'} moduleType
142
+ * @returns {string|undefined} `undefined` when `dc-polyfill` cannot be resolved
143
+ */
144
+ function getDcPolyfillSpecifier (moduleType) {
145
+ try {
146
+ const resolved = require.resolve('dc-polyfill')
147
+
148
+ return moduleType === 'esm' ? pathToFileURL(resolved).href : resolved.replaceAll('\\', '/')
149
+ } catch {
150
+ // The `dc-polyfill` module is unavailable for some reason (like bundling).
151
+ // Let's just keep the default of using `diagnostics-channel` as a fallback
152
+ // which works for most Node versions.
153
+ }
154
+ }
155
+
91
156
  /** @typedef {{ buffer: ArrayBuffer | SharedArrayBuffer, byteLength: number, byteOffset: number }} BufferView */
92
157
 
93
158
  /**
@@ -100,29 +100,4 @@ module.exports = [
100
100
  },
101
101
  channelName: 'resolveLanguageModel',
102
102
  },
103
- // tool
104
- {
105
- module: {
106
- name: 'ai',
107
- versionRange: '>=4.0.0 <7.0.0',
108
- filePath: 'dist/index.js',
109
- },
110
- functionQuery: {
111
- functionName: 'tool',
112
- kind: 'Sync',
113
- },
114
- channelName: 'tool',
115
- },
116
- {
117
- module: {
118
- name: 'ai',
119
- versionRange: '>=4.0.0 <7.0.0',
120
- filePath: 'dist/index.mjs',
121
- },
122
- functionQuery: {
123
- functionName: 'tool',
124
- kind: 'Sync',
125
- },
126
- channelName: 'tool',
127
- },
128
103
  ]
@@ -0,0 +1,83 @@
1
+ 'use strict'
2
+
3
+ // Match the private closure only while its captured identifiers retain the verified
4
+ // 0.8 contract. A future rewrite then misses safely instead of injecting stale names.
5
+ const CREATE_BOUND_QUERY = 'FunctionDeclaration[id.name="createBoundQuery"]' +
6
+ '[params.0.name="compilationContext"][params.1.name="document"][params.4.name="operationName"]'
7
+ const WRAP_QUERY = `${CREATE_BOUND_QUERY} ` +
8
+ 'VariableDeclarator[id.name="ret"] > ObjectExpression > Property > FunctionExpression'
9
+ const BUILD_COMPILATION_CONTEXT = 'FunctionDeclaration[id.name="buildCompilationContext"]' +
10
+ '[params.0.name="schema"][params.1.name="document"][params.2.name="options"][params.3.name="operationName"]'
11
+ const COMPILE_OBJECT_TYPE = 'FunctionDeclaration[id.name="compileObjectType"]' +
12
+ '[params.0.name="context"][params.1.name="type"][params.2.name="fieldNodes"]' +
13
+ '[params.3.name="originPaths"][params.5.name="responsePath"][params.8.name="alwaysDefer"]' +
14
+ ':has(VariableDeclarator[id.name="field"])'
15
+ const COMPILE_DEFERRED_FIELD = 'FunctionDeclaration[id.name="compileDeferredField"]' +
16
+ '[params.0.name="context"][params.1.name="deferredField"]'
17
+
18
+ /**
19
+ * @typedef {{
20
+ * module: { name: string, versionRange: string, filePath: string },
21
+ * astQuery: string,
22
+ * functionQuery?: { kind: 'Sync' },
23
+ * transform?: string,
24
+ * channelName?: string
25
+ * }} GraphqlJitInstrumentation
26
+ */
27
+
28
+ /**
29
+ * @param {GraphqlJitInstrumentation[]} instrumentations
30
+ * @param {string} versionRange
31
+ * @param {string} filePath
32
+ */
33
+ function addInstrumentations (instrumentations, versionRange, filePath) {
34
+ const moduleDefinition = { name: 'graphql-jit', versionRange, filePath }
35
+ instrumentations.push(
36
+ {
37
+ module: moduleDefinition,
38
+ astQuery: BUILD_COMPILATION_CONTEXT,
39
+ functionQuery: { kind: 'Sync' },
40
+ channelName: 'compile',
41
+ },
42
+ {
43
+ module: moduleDefinition,
44
+ astQuery: COMPILE_OBJECT_TYPE,
45
+ transform: 'configureGraphqlJitCompileObject',
46
+ },
47
+ {
48
+ module: moduleDefinition,
49
+ astQuery: COMPILE_DEFERRED_FIELD,
50
+ transform: 'configureGraphqlJitDeferredField',
51
+ },
52
+ {
53
+ module: moduleDefinition,
54
+ astQuery: CREATE_BOUND_QUERY,
55
+ transform: 'configureGraphqlJitRuntime',
56
+ },
57
+ {
58
+ module: moduleDefinition,
59
+ astQuery: WRAP_QUERY,
60
+ functionQuery: { kind: 'Sync' },
61
+ channelName: 'apm:graphql:execute',
62
+ },
63
+ {
64
+ module: moduleDefinition,
65
+ astQuery: WRAP_QUERY,
66
+ transform: 'configureGraphqlJitExecute',
67
+ channelName: 'apm:graphql:execute',
68
+ }
69
+ )
70
+ }
71
+
72
+ /**
73
+ * @type {GraphqlJitInstrumentation[]}
74
+ */
75
+ const instrumentations = []
76
+ // graphql-jit 0.7 and 0.8.0 use this layout and remain compatible with GraphQL 15 and 16.
77
+ // GraphQL 17 compatibility starts at 0.8.1.
78
+ addInstrumentations(instrumentations, '>=0.7.0 <0.8.5 || >=0.8.7 <0.9.0', 'dist/execution.js')
79
+ addInstrumentations(instrumentations, '>=0.8.5 <0.8.7', 'dist/cjs/execution.js')
80
+ addInstrumentations(instrumentations, '>=0.8.5 <0.8.7', 'dist/esm/execution.js')
81
+ addInstrumentations(instrumentations, '>=0.8.7 <0.9.0', 'dist/execution.mjs')
82
+
83
+ module.exports = instrumentations