dd-trace 6.12.0 → 6.14.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 (251) 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/cypress.js +9 -11
  8. package/ci/test-optimization-validation/framework-adapters/vitest.js +3 -3
  9. package/ci/test-optimization-validation/package-check.js +1 -1
  10. package/ci/test-optimization-validation/report-writer.js +7 -5
  11. package/ci/test-optimization-validation/scenarios/ci-wiring.js +5 -4
  12. package/ci/vitest-no-worker-init-runner-setup.mjs +8 -0
  13. package/ci/vitest-no-worker-init-setup.mjs +13 -13
  14. package/ci/vitest-no-worker-init-v5-setup.mjs +4 -0
  15. package/index.d.ts +127 -26
  16. package/package.json +22 -19
  17. package/packages/datadog-esbuild/index.js +3 -1
  18. package/packages/datadog-instrumentations/src/bunyan.js +4 -2
  19. package/packages/datadog-instrumentations/src/cypress-config.js +19 -17
  20. package/packages/datadog-instrumentations/src/fs.js +24 -20
  21. package/packages/datadog-instrumentations/src/google-cloud-vertexai.js +2 -2
  22. package/packages/datadog-instrumentations/src/graphql.js +16 -16
  23. package/packages/datadog-instrumentations/src/helpers/bunyan.js +12 -3
  24. package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +504 -0
  25. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  26. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +266 -0
  27. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +1 -2
  28. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +95 -30
  29. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +0 -25
  30. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql-jit.js +83 -0
  31. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/graphql.js +85 -1
  32. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  33. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/mercurius.js +30 -12
  34. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +13 -0
  35. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +279 -0
  36. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +12 -1
  37. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +562 -27
  38. package/packages/datadog-instrumentations/src/jest.js +165 -38
  39. package/packages/datadog-instrumentations/src/knex.js +76 -0
  40. package/packages/datadog-instrumentations/src/mariadb-bundle.js +1597 -0
  41. package/packages/datadog-instrumentations/src/mariadb.js +13 -0
  42. package/packages/datadog-instrumentations/src/mocha/common.js +59 -2
  43. package/packages/datadog-instrumentations/src/mocha/main.js +25 -15
  44. package/packages/datadog-instrumentations/src/mocha/utils.js +2 -1
  45. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +98 -0
  46. package/packages/datadog-instrumentations/src/mocha/worker.js +12 -8
  47. package/packages/datadog-instrumentations/src/net.js +14 -17
  48. package/packages/datadog-instrumentations/src/next.js +212 -62
  49. package/packages/datadog-instrumentations/src/openai.js +42 -40
  50. package/packages/datadog-instrumentations/src/pg.js +15 -0
  51. package/packages/datadog-instrumentations/src/pino.js +15 -4
  52. package/packages/datadog-instrumentations/src/playwright.js +137 -27
  53. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +40 -0
  54. package/packages/datadog-instrumentations/src/sequelize.js +94 -2
  55. package/packages/datadog-instrumentations/src/undici.js +53 -4
  56. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +44 -7
  57. package/packages/datadog-instrumentations/src/vitest-main.js +92 -9
  58. package/packages/datadog-instrumentations/src/vitest-worker.js +82 -14
  59. package/packages/datadog-instrumentations/src/webdriverio.js +986 -1
  60. package/packages/datadog-instrumentations/src/winston.js +6 -3
  61. package/packages/datadog-plugin-amqp10/src/consumer.js +3 -1
  62. package/packages/datadog-plugin-amqp10/src/producer.js +3 -1
  63. package/packages/datadog-plugin-amqp10/src/util.js +2 -1
  64. package/packages/datadog-plugin-avsc/src/schema_iterator.js +6 -1
  65. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +16 -5
  66. package/packages/datadog-plugin-cassandra-driver/src/index.js +8 -3
  67. package/packages/datadog-plugin-cucumber/src/index.js +0 -2
  68. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +262 -48
  69. package/packages/datadog-plugin-cypress/src/support.js +1 -0
  70. package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -1
  71. package/packages/datadog-plugin-graphql/src/execute.js +998 -196
  72. package/packages/datadog-plugin-graphql/src/index.js +27 -7
  73. package/packages/datadog-plugin-graphql/src/jit.js +136 -0
  74. package/packages/datadog-plugin-graphql/src/request.js +18 -27
  75. package/packages/datadog-plugin-graphql/src/resolve-error.js +108 -0
  76. package/packages/datadog-plugin-graphql/src/tools/signature.js +1 -2
  77. package/packages/datadog-plugin-graphql/src/tools/transforms.js +45 -3
  78. package/packages/datadog-plugin-graphql/src/utils.js +208 -120
  79. package/packages/datadog-plugin-graphql/src/validate.js +10 -23
  80. package/packages/datadog-plugin-http/src/client.js +2 -15
  81. package/packages/datadog-plugin-http2/src/client.js +2 -15
  82. package/packages/datadog-plugin-jest/src/index.js +0 -6
  83. package/packages/datadog-plugin-langchain/src/tracing.js +7 -0
  84. package/packages/datadog-plugin-mocha/src/index.js +403 -75
  85. package/packages/datadog-plugin-mongodb-core/src/query.js +6 -0
  86. package/packages/datadog-plugin-mysql/src/index.js +41 -15
  87. package/packages/datadog-plugin-net/src/tcp.js +3 -1
  88. package/packages/datadog-plugin-next/src/index.js +63 -29
  89. package/packages/datadog-plugin-openai-agents/src/integration.js +15 -11
  90. package/packages/datadog-plugin-playwright/src/index.js +176 -28
  91. package/packages/datadog-plugin-undici/src/index.js +29 -56
  92. package/packages/datadog-plugin-vitest/src/index.js +6 -12
  93. package/packages/dd-trace/src/aiguard/evaluation.js +96 -21
  94. package/packages/dd-trace/src/aiguard/integrations/vercel-ai.js +2 -3
  95. package/packages/dd-trace/src/aiguard/messages/anthropic.js +29 -10
  96. package/packages/dd-trace/src/aiguard/messages/openai.js +8 -1
  97. package/packages/dd-trace/src/aiguard/messages/vercel-ai.js +20 -6
  98. package/packages/dd-trace/src/aiguard/noop.js +9 -1
  99. package/packages/dd-trace/src/aiguard/redaction.js +183 -0
  100. package/packages/dd-trace/src/aiguard/sdk.js +7 -2
  101. package/packages/dd-trace/src/aiguard/tags.js +2 -0
  102. package/packages/dd-trace/src/appsec/api_security/index.js +23 -6
  103. package/packages/dd-trace/src/appsec/api_security/sampler.js +99 -40
  104. package/packages/dd-trace/src/appsec/graphql.js +6 -2
  105. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +3 -3
  106. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -1
  107. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +8 -2
  108. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +11 -36
  109. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +1 -1
  110. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +10 -9
  111. package/packages/dd-trace/src/appsec/lambda.js +44 -26
  112. package/packages/dd-trace/src/appsec/rule_manager.js +2 -0
  113. package/packages/dd-trace/src/ci-visibility/encode/json-encoder.js +32 -2
  114. package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +8 -8
  115. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +6 -4
  116. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +20 -4
  117. package/packages/dd-trace/src/ci-visibility/exporters/agentless/request-tracker.js +7 -150
  118. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +7 -6
  119. package/packages/dd-trace/src/ci-visibility/exporters/agents.js +54 -0
  120. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/writer.js +1 -2
  121. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +397 -234
  122. package/packages/dd-trace/src/ci-visibility/exporters/limits.js +9 -0
  123. package/packages/dd-trace/src/ci-visibility/exporters/request.js +323 -31
  124. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +42 -0
  125. package/packages/dd-trace/src/ci-visibility/final-flush.js +21 -0
  126. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +57 -18
  127. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +0 -3
  128. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +164 -71
  129. package/packages/dd-trace/src/ci-visibility/requests/video-request.js +176 -0
  130. package/packages/dd-trace/src/ci-visibility/telemetry.js +10 -7
  131. package/packages/dd-trace/src/ci-visibility/test-video.js +61 -0
  132. package/packages/dd-trace/src/config/generated-config-types.d.ts +10 -0
  133. package/packages/dd-trace/src/config/index.js +75 -14
  134. package/packages/dd-trace/src/config/parsers.js +11 -1
  135. package/packages/dd-trace/src/config/stable.js +3 -3
  136. package/packages/dd-trace/src/config/supported-configurations.json +47 -2
  137. package/packages/dd-trace/src/crashtracking/crashtracker.js +82 -18
  138. package/packages/dd-trace/src/debugger/config.js +12 -1
  139. package/packages/dd-trace/src/debugger/constants.js +1 -0
  140. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +2 -1
  141. package/packages/dd-trace/src/debugger/devtools_client/request-options.js +33 -0
  142. package/packages/dd-trace/src/debugger/devtools_client/send.js +7 -39
  143. package/packages/dd-trace/src/debugger/devtools_client/status.js +11 -6
  144. package/packages/dd-trace/src/debugger/devtools_client/tags.js +41 -0
  145. package/packages/dd-trace/src/debugger/index.js +23 -3
  146. package/packages/dd-trace/src/dogstatsd.js +532 -71
  147. package/packages/dd-trace/src/encode/0.4-cross-payload.js +170 -0
  148. package/packages/dd-trace/src/encode/0.4.js +5 -5
  149. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +9 -8
  150. package/packages/dd-trace/src/evp_proxy/direct.js +27 -23
  151. package/packages/dd-trace/src/exporters/agent/index.js +24 -3
  152. package/packages/dd-trace/src/exporters/agent/writer.js +28 -11
  153. package/packages/dd-trace/src/exporters/agentless/index.js +7 -9
  154. package/packages/dd-trace/src/exporters/agentless/writer.js +100 -118
  155. package/packages/dd-trace/src/exporters/common/agents.js +28 -6
  156. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -2
  157. package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +191 -0
  158. package/packages/dd-trace/src/exporters/common/request.js +31 -11
  159. package/packages/dd-trace/src/exporters/common/url.js +40 -1
  160. package/packages/dd-trace/src/exporters/common/writer.js +31 -7
  161. package/packages/dd-trace/src/exporters/span-stats/index.js +23 -4
  162. package/packages/dd-trace/src/external-logger/src/index.js +4 -3
  163. package/packages/dd-trace/src/flush.js +105 -0
  164. package/packages/dd-trace/src/id.js +14 -0
  165. package/packages/dd-trace/src/index.js +5 -2
  166. package/packages/dd-trace/src/llmobs/experiments/client.js +4 -0
  167. package/packages/dd-trace/src/llmobs/experiments/dataset.js +52 -2
  168. package/packages/dd-trace/src/llmobs/experiments/experiment.js +420 -105
  169. package/packages/dd-trace/src/llmobs/experiments/index.js +54 -42
  170. package/packages/dd-trace/src/llmobs/experiments/noop.js +39 -8
  171. package/packages/dd-trace/src/llmobs/experiments/result.js +1 -0
  172. package/packages/dd-trace/src/llmobs/experiments/util.js +21 -0
  173. package/packages/dd-trace/src/llmobs/index.js +111 -48
  174. package/packages/dd-trace/src/llmobs/noop.js +2 -1
  175. package/packages/dd-trace/src/llmobs/plugins/ai/ddTelemetry.js +22 -71
  176. package/packages/dd-trace/src/llmobs/plugins/ai/vercelTelemetry.js +23 -13
  177. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +8 -4
  178. package/packages/dd-trace/src/llmobs/plugins/claude-agent-sdk/index.js +6 -3
  179. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +7 -0
  180. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +13 -6
  181. package/packages/dd-trace/src/llmobs/plugins/openai-agents/utils.js +5 -7
  182. package/packages/dd-trace/src/llmobs/util.js +0 -33
  183. package/packages/dd-trace/src/llmobs/writers/base.js +106 -53
  184. package/packages/dd-trace/src/log/index.js +7 -1
  185. package/packages/dd-trace/src/log-submission/log-submission-plugin.js +249 -0
  186. package/packages/dd-trace/src/noop/span.js +5 -0
  187. package/packages/dd-trace/src/openfeature/writers/base.js +14 -12
  188. package/packages/dd-trace/src/openfeature/writers/exposures.js +8 -1
  189. package/packages/dd-trace/src/openfeature/writers/util.js +1 -1
  190. package/packages/dd-trace/src/opentelemetry/logs/batch_log_processor.js +45 -3
  191. package/packages/dd-trace/src/opentelemetry/logs/index.js +9 -25
  192. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +7 -4
  193. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +14 -4
  194. package/packages/dd-trace/src/opentelemetry/metrics/index.js +18 -23
  195. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +8 -0
  196. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +18 -6
  197. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_exporter.js +14 -2
  198. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +25 -5
  199. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +61 -25
  200. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +19 -4
  201. package/packages/dd-trace/src/opentelemetry/resource-attributes.js +55 -0
  202. package/packages/dd-trace/src/opentelemetry/trace/index.js +6 -1
  203. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +10 -0
  204. package/packages/dd-trace/src/opentelemetry/tracer.js +26 -2
  205. package/packages/dd-trace/src/opentracing/propagation/text_map.js +494 -351
  206. package/packages/dd-trace/src/opentracing/span.js +28 -0
  207. package/packages/dd-trace/src/otel-thread-ctx.js +23 -5
  208. package/packages/dd-trace/src/payload-tagging/index.js +2 -1
  209. package/packages/dd-trace/src/plugin_manager.js +2 -0
  210. package/packages/dd-trace/src/plugins/ci_plugin.js +1 -6
  211. package/packages/dd-trace/src/plugins/tracing.js +12 -10
  212. package/packages/dd-trace/src/plugins/util/ci.js +3 -1
  213. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +16 -15
  214. package/packages/dd-trace/src/plugins/util/status-validator.js +98 -0
  215. package/packages/dd-trace/src/plugins/util/test.js +157 -41
  216. package/packages/dd-trace/src/plugins/util/url.js +2 -2
  217. package/packages/dd-trace/src/plugins/util/web.js +6 -74
  218. package/packages/dd-trace/src/profiling/config.js +1 -0
  219. package/packages/dd-trace/src/profiling/oom.js +11 -5
  220. package/packages/dd-trace/src/profiling/profiler.js +30 -13
  221. package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
  222. package/packages/dd-trace/src/profiling/profilers/space.js +38 -11
  223. package/packages/dd-trace/src/profiling/profilers/wall.js +14 -14
  224. package/packages/dd-trace/src/profiling/webspan-utils.js +7 -4
  225. package/packages/dd-trace/src/proxy.js +108 -10
  226. package/packages/dd-trace/src/remote_config/index.js +319 -101
  227. package/packages/dd-trace/src/remote_config/scheduler.js +37 -12
  228. package/packages/dd-trace/src/runtime_metrics/client.js +37 -8
  229. package/packages/dd-trace/src/runtime_metrics/index.js +5 -0
  230. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +10 -1
  231. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +22 -7
  232. package/packages/dd-trace/src/sampling_rule.js +36 -9
  233. package/packages/dd-trace/src/serverless/telemetry-delivery-tracker.js +51 -0
  234. package/packages/dd-trace/src/serverless/vercel.js +155 -0
  235. package/packages/dd-trace/src/serverless.js +45 -21
  236. package/packages/dd-trace/src/service-naming/schemas/util.js +1 -1
  237. package/packages/dd-trace/src/span_stats.js +64 -31
  238. package/packages/dd-trace/src/startup-log.js +3 -2
  239. package/packages/dd-trace/src/telemetry/agentless-url.js +28 -0
  240. package/packages/dd-trace/src/telemetry/send-data.js +18 -16
  241. package/packages/dd-trace/src/telemetry/session-propagation.js +3 -2
  242. package/packages/dd-trace/src/tracer.js +26 -5
  243. package/packages/dd-trace/src/tracer_metadata.js +11 -3
  244. package/packages/dd-trace/src/web-tags-cache.js +67 -13
  245. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
  246. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  247. package/vendor/dist/protobufjs/index.js +1 -1
  248. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  249. package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +0 -27
  250. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +0 -53
  251. package/packages/dd-trace/src/encode/agentless-json.js +0 -209
@@ -0,0 +1,170 @@
1
+ 'use strict'
2
+
3
+ const { AgentEncoder } = require('./0.4')
4
+
5
+ const CROSS_PAYLOAD_CACHE_LIMIT = 256
6
+ const CROSS_PAYLOAD_CANDIDATE_LIMIT = 512
7
+ const CROSS_PAYLOAD_LEARNING_PAYLOAD_LIMIT = 8
8
+ const CROSS_PAYLOAD_MISS_LIMIT = 32
9
+ const CROSS_PAYLOAD_STRING_LIMIT = 256
10
+
11
+ class CrossPayloadAgentEncoder extends AgentEncoder {
12
+ #disableCrossPayloadCache
13
+ #crossPayloadState = createCrossPayloadState()
14
+
15
+ /**
16
+ * @param {{ flush: () => void }} writer
17
+ * @param {() => void} disableCrossPayloadCache
18
+ */
19
+ constructor (writer, disableCrossPayloadCache) {
20
+ super(writer)
21
+ this.#disableCrossPayloadCache = disableCrossPayloadCache
22
+ }
23
+
24
+ /**
25
+ * @param {string} value
26
+ * @param {boolean} [stable]
27
+ * @returns {Buffer}
28
+ */
29
+ _cacheString (value, stable = false) {
30
+ if (!stable) return super._cacheString(value)
31
+
32
+ const crossPayloadState = this.#crossPayloadState
33
+ if (crossPayloadState === undefined || value.length === 0 || value.length > CROSS_PAYLOAD_STRING_LIMIT) {
34
+ return super._cacheString(value)
35
+ }
36
+
37
+ const learning = crossPayloadState.learningPayloadCount < CROSS_PAYLOAD_LEARNING_PAYLOAD_LIMIT
38
+ if (learning) markPayloadString(crossPayloadState, value)
39
+ const retainedEntry = crossPayloadState.stringMap?.[value]
40
+ if (retainedEntry !== undefined) {
41
+ if (!learning && crossPayloadState.hitCount < CROSS_PAYLOAD_MISS_LIMIT) {
42
+ crossPayloadState.hitCount++
43
+ }
44
+ const start = this._stringBytes.length
45
+ this._stringBytes.set(retainedEntry)
46
+ const entry = this._stringBytes.buffer.subarray(start, start + retainedEntry.length)
47
+ this._stringMap[value] = entry
48
+ return entry
49
+ }
50
+ if (!learning && crossPayloadState.missCount < CROSS_PAYLOAD_MISS_LIMIT) {
51
+ crossPayloadState.missCount++
52
+ }
53
+ if (!learning || crossPayloadState.payloadStableStrings?.[value] !== true) {
54
+ return super._cacheString(value)
55
+ }
56
+
57
+ let entry = super._cacheString(value)
58
+ if (entry.length > CROSS_PAYLOAD_STRING_LIMIT) return entry
59
+
60
+ const previousPayloadStrings = crossPayloadState.previousPayloadStrings
61
+ if (previousPayloadStrings?.[value] !== undefined &&
62
+ crossPayloadState.stringCount < CROSS_PAYLOAD_CACHE_LIMIT) {
63
+ entry = Buffer.from(entry)
64
+ crossPayloadState.stringMap ??= Object.create(null)
65
+ crossPayloadState.stringMap[value] = entry
66
+ crossPayloadState.stringCount++
67
+ }
68
+ return entry
69
+ }
70
+
71
+ /** @returns {Buffer} */
72
+ makePayload () {
73
+ this.#prepareReset()
74
+ return super.makePayload()
75
+ }
76
+
77
+ /** @returns {void} */
78
+ reset () {
79
+ this.#prepareReset()
80
+ super.reset()
81
+ }
82
+
83
+ /** @returns {void} */
84
+ #prepareReset () {
85
+ const crossPayloadState = this.#crossPayloadState
86
+ if (crossPayloadState !== undefined && !prepareCrossPayloadReset(crossPayloadState)) {
87
+ this.#crossPayloadState = undefined
88
+ this.#disableCrossPayloadCache()
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * @param {{ flush: () => void }} writer
95
+ * @param {() => void} disableCrossPayloadCache
96
+ * @returns {AgentEncoder}
97
+ */
98
+ function createAgentEncoder (writer, disableCrossPayloadCache) {
99
+ return new CrossPayloadAgentEncoder(writer, disableCrossPayloadCache)
100
+ }
101
+
102
+ function createCrossPayloadState () {
103
+ return {
104
+ hitCount: 0,
105
+ learningPayloadCount: 0,
106
+ lowUseCount: 0,
107
+ missCount: 0,
108
+ payloadStableStringCount: 0,
109
+ payloadStableStrings: undefined,
110
+ previousPayloadStrings: undefined,
111
+ stringCount: 0,
112
+ stringMap: undefined,
113
+ }
114
+ }
115
+
116
+ /**
117
+ * @param {ReturnType<typeof createCrossPayloadState>} crossPayloadState
118
+ * @param {string} value
119
+ */
120
+ function markPayloadString (crossPayloadState, value) {
121
+ if (crossPayloadState.payloadStableStringCount >= CROSS_PAYLOAD_CANDIDATE_LIMIT ||
122
+ crossPayloadState.payloadStableStrings?.[value] !== undefined) {
123
+ return
124
+ }
125
+ crossPayloadState.payloadStableStrings ??= Object.create(null)
126
+ crossPayloadState.payloadStableStrings[value] = true
127
+ crossPayloadState.payloadStableStringCount++
128
+ }
129
+
130
+ /**
131
+ * @param {ReturnType<typeof createCrossPayloadState>} crossPayloadState
132
+ * @returns {boolean}
133
+ */
134
+ function prepareCrossPayloadReset (crossPayloadState) {
135
+ const learning = crossPayloadState.learningPayloadCount < CROSS_PAYLOAD_LEARNING_PAYLOAD_LIMIT
136
+ const lowUse = !learning && crossPayloadState.hitCount < crossPayloadState.missCount
137
+ if (lowUse) {
138
+ crossPayloadState.lowUseCount++
139
+ if (crossPayloadState.lowUseCount >= 2) return false
140
+ crossPayloadState.learningPayloadCount = 0
141
+ crossPayloadState.stringCount = 0
142
+ crossPayloadState.stringMap = undefined
143
+ crossPayloadState.payloadStableStrings = undefined
144
+ crossPayloadState.payloadStableStringCount = 0
145
+ crossPayloadState.previousPayloadStrings = undefined
146
+ crossPayloadState.hitCount = 0
147
+ crossPayloadState.missCount = 0
148
+ return true
149
+ }
150
+ if (!learning && crossPayloadState.hitCount > 0) {
151
+ crossPayloadState.lowUseCount = 0
152
+ }
153
+
154
+ if (learning) {
155
+ crossPayloadState.learningPayloadCount++
156
+ if (crossPayloadState.learningPayloadCount < CROSS_PAYLOAD_LEARNING_PAYLOAD_LIMIT) {
157
+ crossPayloadState.previousPayloadStrings = crossPayloadState.payloadStableStrings
158
+ } else {
159
+ crossPayloadState.previousPayloadStrings = undefined
160
+ if (crossPayloadState.stringMap === undefined) return false
161
+ }
162
+ }
163
+ crossPayloadState.payloadStableStrings = undefined
164
+ crossPayloadState.payloadStableStringCount = 0
165
+ crossPayloadState.hitCount = 0
166
+ crossPayloadState.missCount = 0
167
+ return true
168
+ }
169
+
170
+ module.exports = { createAgentEncoder }
@@ -339,11 +339,11 @@ class AgentEncoder {
339
339
  // Replaces up to ten separate `bytes.reserve` calls per span with one.
340
340
  let typeEntry
341
341
  if (span.type) {
342
- typeEntry = stringMap[span.type] ?? this._cacheString(span.type)
342
+ typeEntry = stringMap[span.type] ?? this._cacheString(span.type, true)
343
343
  }
344
- const nameEntry = stringMap[span.name] ?? this._cacheString(span.name)
345
- const resourceEntry = stringMap[span.resource] ?? this._cacheString(span.resource)
346
- const serviceEntry = stringMap[span.service] ?? this._cacheString(span.service)
344
+ const nameEntry = stringMap[span.name] ?? this._cacheString(span.name, true)
345
+ const resourceEntry = stringMap[span.resource] ?? this._cacheString(span.resource, true)
346
+ const serviceEntry = stringMap[span.service] ?? this._cacheString(span.service, true)
347
347
  const nameLen = nameEntry.length
348
348
  const resourceLen = resourceEntry.length
349
349
  const serviceLen = serviceEntry.length
@@ -589,7 +589,7 @@ class AgentEncoder {
589
589
  const entryValue = value[key]
590
590
  if (typeof entryValue !== 'string' && typeof entryValue !== 'number') continue
591
591
 
592
- const keyEntry = stringMap[key] ?? this._cacheString(key)
592
+ const keyEntry = stringMap[key] ?? this._cacheString(key, true)
593
593
  const keyEntryLen = keyEntry.length
594
594
  const writeOffset = bytes.length
595
595
 
@@ -69,11 +69,11 @@ function truncateTestLevelMetadataTags (tags) {
69
69
  }
70
70
 
71
71
  class AgentlessCiVisibilityEncoder extends AgentEncoder {
72
- constructor (writer, { runtimeId, service, env }) {
72
+ constructor (writer, { tags }) {
73
73
  super(writer, INTAKE_SOFT_LIMIT)
74
- this.runtimeId = runtimeId
75
- this.service = service
76
- this.env = env
74
+ // Holds a reference to the live `tags` object (instead of copying `env`/`runtime-id` out of it)
75
+ // so a later change (e.g. a MicroVM clone resume) is picked up at flush time.
76
+ this.tags = tags
77
77
 
78
78
  // Used to keep track of the number of encoded events to update the
79
79
  // length of `payload.events` when calling `makePayload`
@@ -406,11 +406,12 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
406
406
  events: [],
407
407
  }
408
408
 
409
- if (this.env) {
410
- payload.metadata['*'].env = this.env
409
+ if (this.tags.env) {
410
+ payload.metadata['*'].env = this.tags.env
411
411
  }
412
- if (this.runtimeId) {
413
- payload.metadata['*']['runtime-id'] = this.runtimeId
412
+ const runtimeId = this.tags['runtime-id']
413
+ if (runtimeId) {
414
+ payload.metadata['*']['runtime-id'] = runtimeId
414
415
  }
415
416
 
416
417
  bytes.writeMapPrefix(Object.keys(payload).length)
@@ -1,11 +1,13 @@
1
1
  'use strict'
2
2
 
3
- const { format } = require('node:url')
4
-
5
3
  const { HttpsProxyAgent } = require('../../../../vendor/dist/https-proxy-agent')
6
4
  const { getProxyForUrl } = require('../../../../vendor/dist/proxy-from-env')
5
+ const { createSiteUrl } = require('../exporters/common/url')
7
6
  const log = require('../log')
8
7
 
8
+ /** @type {Map<string, import('node:https').Agent>} */
9
+ const proxyAgents = new Map()
10
+
9
11
  /**
10
12
  * @typedef {object} DirectEVPRoute
11
13
  * @property {URL} url - Direct intake URL
@@ -28,37 +30,39 @@ function createDirectEVPRoute (config, intake) {
28
30
  if (!apiKey || !config.site) return
29
31
 
30
32
  try {
31
- const hostname = `${intake}.${config.site}`.toLowerCase()
32
- const url = new URL(format({
33
- protocol: 'https:',
34
- hostname,
35
- }))
36
- if (
37
- url.hostname !== hostname ||
38
- url.username ||
39
- url.password ||
40
- url.port ||
41
- url.pathname !== '/' ||
42
- url.search ||
43
- url.hash
44
- ) {
45
- throw new Error('Invalid direct EVP intake URL')
46
- }
33
+ const url = createSiteUrl(config.site, intake)
34
+ if (url === undefined) throw new Error('Invalid direct EVP intake URL')
47
35
 
48
- const proxyUrl = getProxyForUrl(url.href)
49
- const agent = proxyUrl ? new HttpsProxyAgent(proxyUrl) : undefined
36
+ const agent = getHttpsProxyAgent(url.href)
50
37
 
51
- return {
38
+ const route = {
52
39
  url,
53
40
  basePath: '',
54
41
  headers: {
55
42
  'DD-API-KEY': apiKey,
56
43
  },
57
- ...(agent && { agent }),
58
44
  }
45
+ if (agent) route.agent = agent
46
+ return route
59
47
  } catch (error) {
60
48
  log.debug('Unable to configure direct EVP intake: %s', error.message)
61
49
  }
62
50
  }
63
51
 
64
- module.exports = { createDirectEVPRoute }
52
+ /**
53
+ * @param {string} url
54
+ * @returns {import('node:https').Agent|undefined}
55
+ */
56
+ function getHttpsProxyAgent (url) {
57
+ const proxyUrl = getProxyForUrl(url)
58
+ if (!proxyUrl) return
59
+
60
+ let agent = proxyAgents.get(proxyUrl)
61
+ if (agent === undefined) {
62
+ agent = new HttpsProxyAgent(proxyUrl)
63
+ proxyAgents.set(proxyUrl, agent)
64
+ }
65
+ return agent
66
+ }
67
+
68
+ module.exports = { createDirectEVPRoute, getHttpsProxyAgent }
@@ -2,14 +2,17 @@
2
2
 
3
3
  const { URL } = require('url')
4
4
  const log = require('../../log')
5
+ const { createServerlessDeliveryTracker } = require('../../serverless')
5
6
  const Writer = require('./writer')
6
7
 
7
8
  class AgentExporter {
8
9
  #timer
10
+ #serverlessDeliveryTracker
9
11
 
10
12
  constructor (config, prioritySampler) {
13
+ this.#serverlessDeliveryTracker = createServerlessDeliveryTracker()
11
14
  this._config = config
12
- const { lookup, protocolVersion, stats = {}, apmTracingEnabled } = config
15
+ const { lookup, protocolVersion, stats = {}, apmTracingEnabled, flushInterval } = config
13
16
  this._url = config.url
14
17
 
15
18
  const headers = {}
@@ -22,7 +25,9 @@ class AgentExporter {
22
25
  prioritySampler,
23
26
  lookup,
24
27
  protocolVersion,
28
+ flushInterval,
25
29
  headers,
30
+ deliveryTracker: this.#serverlessDeliveryTracker,
26
31
  })
27
32
 
28
33
  globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(this.flush.bind(this))
@@ -54,10 +59,26 @@ class AgentExporter {
54
59
  }
55
60
  }
56
61
 
57
- flush (done = () => {}) {
62
+ flush (done) {
58
63
  clearTimeout(this.#timer)
59
64
  this.#timer = undefined
60
- this._writer.flush(done)
65
+
66
+ if (!this.#serverlessDeliveryTracker) {
67
+ try {
68
+ return this._writer.flush(done)
69
+ } catch (error) {
70
+ log.error('Failed to flush traces: %s', error.message)
71
+ done?.()
72
+ return
73
+ }
74
+ }
75
+
76
+ try {
77
+ this._writer.flush()
78
+ } catch (error) {
79
+ log.error('Failed to flush traces: %s', error.message)
80
+ }
81
+ this.#serverlessDeliveryTracker.waitForIdle(done)
61
82
  }
62
83
  }
63
84
 
@@ -19,18 +19,19 @@ class AgentWriter extends BaseWriter {
19
19
  #requestTracker
20
20
 
21
21
  constructor (...args) {
22
+ const { isTestOptimization } = args[0]
22
23
  super({
23
24
  ...args[0],
24
25
  beforeFirstFlush: () => firstFlushChannel.publish(),
26
+ retainOnBackpressure: isTestOptimization,
25
27
  })
26
- const { prioritySampler, lookup, protocolVersion, headers, isTestOptimization } = args[0]
27
- const AgentEncoder = getEncoder(protocolVersion)
28
+ const { prioritySampler, lookup, protocolVersion, flushInterval, headers } = args[0]
28
29
 
29
30
  this._prioritySampler = prioritySampler
30
31
  this._lookup = lookup
31
32
  this._protocolVersion = protocolVersion
32
33
  this._headers = headers
33
- this._encoder = new AgentEncoder(this)
34
+ this._encoder = createEncoder(protocolVersion, flushInterval, this)
34
35
  if (isTestOptimization) {
35
36
  this.#request = require('../../ci-visibility/exporters/request')
36
37
  const TestOptimizationRequestTracker = require('../../ci-visibility/exporters/agentless/request-tracker')
@@ -39,18 +40,18 @@ class AgentWriter extends BaseWriter {
39
40
  }
40
41
 
41
42
  /**
42
- * Flushes payloads, including requests already in flight during Test Optimization finalization.
43
- *
43
+ * Performs the writer flush without registering a serverless delivery.
44
+ * Test Optimization owns its own request lifecycle tracking.
44
45
  * @param {(error?: Error) => void} [done]
45
46
  * @param {{ deadline?: number }} [options]
46
47
  * @returns {void}
47
48
  */
48
- flush (done, options) {
49
+ flushDirect (done, options) {
49
50
  if (this.#requestTracker) {
50
51
  this.#requestTracker.flush(done, options)
51
52
  return
52
53
  }
53
- super.flush(done, options)
54
+ super.flushDirect(done, options)
54
55
  }
55
56
 
56
57
  _sendPayload (data, count, done, flushOptions) {
@@ -113,10 +114,26 @@ class AgentWriter extends BaseWriter {
113
114
  }
114
115
  }
115
116
 
116
- function getEncoder (protocolVersion) {
117
- return protocolVersion === '0.5'
118
- ? require('../../encode/0.5').AgentEncoder
119
- : require('../../encode/0.4').AgentEncoder
117
+ /**
118
+ * @param {string} protocolVersion
119
+ * @param {number | undefined} flushInterval
120
+ * @param {AgentWriter} writer
121
+ * @returns {import('../../encode/0.4').AgentEncoder}
122
+ */
123
+ function createEncoder (protocolVersion, flushInterval, writer) {
124
+ if (protocolVersion === '0.5') {
125
+ const { AgentEncoder } = require('../../encode/0.5')
126
+ return new AgentEncoder(writer)
127
+ }
128
+ if (flushInterval === 0) {
129
+ const { createAgentEncoder } = require('../../encode/0.4-cross-payload')
130
+ const disableCrossPayloadCache = () => {
131
+ writer._encoder = createEncoder('0.4', undefined, writer)
132
+ }
133
+ return createAgentEncoder(writer, disableCrossPayloadCache)
134
+ }
135
+ const { AgentEncoder } = require('../../encode/0.4')
136
+ return new AgentEncoder(writer)
120
137
  }
121
138
 
122
139
  function makeRequest (version, data, count, url, headers, lookup, flushOptions, request, requestTracker, cb) {
@@ -4,8 +4,7 @@ const { URL } = require('node:url')
4
4
  const os = require('node:os')
5
5
 
6
6
  const log = require('../../log')
7
- const { entityId } = require('../common/docker')
8
- const tracerVersion = require('../../../../../package.json').version
7
+ const { containerId } = require('../common/docker')
9
8
  const Writer = require('./writer')
10
9
  const { computeIntakeUrl } = require('./intake')
11
10
 
@@ -23,7 +22,7 @@ class AgentlessExporter {
23
22
  * @param {string} [config.site] - The Datadog site. Defaults to 'datadoghq.com'.
24
23
  * @param {number} [config.flushInterval] - Batch flush interval in ms
25
24
  * @param {string} [config.env] - Environment name
26
- * @param {object} [config.tags] - Tags including runtime-id
25
+ * @param {object} config.tags - Tags including runtime-id
27
26
  */
28
27
  constructor (config) {
29
28
  this.#config = config
@@ -40,13 +39,12 @@ class AgentlessExporter {
40
39
 
41
40
  const metadata = {
42
41
  hostname: os.hostname(),
43
- env: config.env,
44
- languageName: 'nodejs',
45
- languageVersion: process.version,
46
- tracerVersion,
47
- runtimeID: config.tags?.['runtime-id'],
48
- ...(entityId ? { containerID: entityId } : {}),
42
+ // Read live off `config` (instead of copying the value) so a later change
43
+ // (e.g. a MicroVM clone resume) is picked up by the next data-pipeline export.
44
+ get env () { return config.env },
45
+ get runtimeID () { return config.tags['runtime-id'] },
49
46
  }
47
+ if (containerId) metadata.containerId = containerId
50
48
 
51
49
  this._writer = new Writer({
52
50
  url: this._url,