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
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const net = require('node:net')
4
+ const { format } = require('node:url')
4
5
 
5
6
  const { urlToHttpOptions } = require('./url-to-http-options-polyfill')
6
7
 
@@ -16,6 +17,44 @@ function isLoopbackHost (hostname) {
16
17
  (hostname.startsWith('127.') && net.isIPv4(hostname))
17
18
  }
18
19
 
20
+ /**
21
+ * @param {string|undefined} protocol
22
+ * @param {string|undefined} hostname
23
+ * @returns {boolean}
24
+ */
25
+ function canSendApiKey (protocol, hostname) {
26
+ return protocol === 'https:' || protocol === 'unix:' ||
27
+ typeof hostname === 'string' && isLoopbackHost(hostname)
28
+ }
29
+
30
+ /**
31
+ * @param {string} site
32
+ * @param {string} [intake]
33
+ * @returns {URL | undefined}
34
+ */
35
+ function createSiteUrl (site, intake) {
36
+ const hostname = `${intake === undefined ? '' : `${intake}.`}${site}`.toLowerCase()
37
+
38
+ try {
39
+ const url = new URL(format({
40
+ protocol: 'https:',
41
+ hostname,
42
+ }))
43
+ if (
44
+ url.hostname !== hostname ||
45
+ url.username ||
46
+ url.password ||
47
+ url.port ||
48
+ url.pathname !== '/' ||
49
+ url.search ||
50
+ url.hash
51
+ ) {
52
+ return
53
+ }
54
+ return url
55
+ } catch {}
56
+ }
57
+
19
58
  /**
20
59
  * Convert an agent/intake URL into Node http(s) request options.
21
60
  *
@@ -43,4 +82,4 @@ function parseUrl (urlObjOrString) {
43
82
  return url
44
83
  }
45
84
 
46
- module.exports = { isLoopbackHost, parseUrl }
85
+ module.exports = { canSendApiKey, createSiteUrl, isLoopbackHost, parseUrl }
@@ -8,19 +8,44 @@ const request = require('./request')
8
8
  const { safeJSONStringify } = require('./util')
9
9
 
10
10
  const firstFlushChannel = channel('dd-trace:exporter:first-flush')
11
+ const noop = () => {}
11
12
 
12
13
  class Writer {
13
- constructor ({ url, beforeFirstFlush }) {
14
+ #deliveryTracker
15
+ #retainOnBackpressure
16
+
17
+ constructor ({ url, beforeFirstFlush, deliveryTracker, retainOnBackpressure = false }) {
14
18
  this._url = url
15
19
  this._beforeFirstFlush = beforeFirstFlush
20
+ this.#retainOnBackpressure = retainOnBackpressure
21
+ this.#deliveryTracker = deliveryTracker
16
22
  }
17
23
 
18
24
  #isFirstFlush = true
19
25
 
20
- flush (done = () => {}, options) {
26
+ /**
27
+ * Flushes queued telemetry, retaining delivery on supported serverless platforms.
28
+ * @param {(error?: Error) => void} [done]
29
+ * @param {{ deadline?: number }} [options]
30
+ * @returns {void}
31
+ */
32
+ flush (done, options) {
33
+ if (this.#deliveryTracker) {
34
+ return this.#deliveryTracker.track(callback => this.flushDirect(callback, options), done)
35
+ }
36
+ this.flushDirect(done, options)
37
+ }
38
+
39
+ /**
40
+ * Flushes queued telemetry without registering serverless delivery retention.
41
+ * @param {(error?: Error) => void} [done]
42
+ * @param {{ deadline?: number }} [options]
43
+ * @returns {void}
44
+ */
45
+ flushDirect (done = noop, options) {
21
46
  const count = this._encoder.count()
22
47
 
23
- if (!request.writable && options?.deadline === undefined) {
48
+ if (!request.writable && options?.deadline === undefined && !this.#retainOnBackpressure) {
24
49
  this._encoder.reset()
25
50
  done()
26
51
  } else if (count > 0) {
@@ -55,7 +80,7 @@ class Writer {
55
80
  }
56
81
 
57
82
  append (payload, options) {
58
- if (!request.writable && options?.deadline === undefined) {
83
+ if (!request.writable && options?.deadline === undefined && !this.#retainOnBackpressure) {
59
84
  // eslint-disable-next-line eslint-rules/eslint-log-printf-style
60
85
  log.debug(() => `Maximum number of active requests reached. Payload discarded: ${safeJSONStringify(payload)}`)
61
86
  return false
@@ -64,12 +89,11 @@ class Writer {
64
89
  // eslint-disable-next-line eslint-rules/eslint-log-printf-style
65
90
  log.debug(() => `Encoding payload: ${safeJSONStringify(payload)}`)
66
91
 
67
- this._encode(payload)
68
- return true
92
+ return this._encode(payload) !== false
69
93
  }
70
94
 
71
95
  _encode (payload) {
72
- this._encoder.encode(payload)
96
+ return this._encoder.encode(payload)
73
97
  }
74
98
 
75
99
  setUrl (url) {
@@ -1,16 +1,35 @@
1
1
  'use strict'
2
2
 
3
+ const log = require('../../log')
4
+ const { createServerlessDeliveryTracker } = require('../../serverless')
3
5
  const { Writer } = require('./writer')
4
6
 
5
7
  class SpanStatsExporter {
8
+ #serverlessDeliveryTracker
9
+
6
10
  constructor (config) {
11
+ this.#serverlessDeliveryTracker = createServerlessDeliveryTracker()
7
12
  this._url = config.url
8
- this._writer = new Writer({ url: this._url })
13
+ this._writer = new Writer({
14
+ url: this._url,
15
+ deliveryTracker: this.#serverlessDeliveryTracker,
16
+ })
17
+ }
18
+
19
+ export (payload, done) {
20
+ try {
21
+ this._writer.append(payload)
22
+ this._writer.flush(this.#serverlessDeliveryTracker ? undefined : done)
23
+ } catch (error) {
24
+ if (!done) throw error
25
+ log.error('Failed to flush span stats: %s', error.message)
26
+ }
27
+ this.#serverlessDeliveryTracker?.waitForIdle(done)
9
28
  }
10
29
 
11
- export (payload) {
12
- this._writer.append(payload)
13
- this._writer.flush()
30
+ flush (done) {
31
+ this._writer.flush(this.#serverlessDeliveryTracker ? undefined : done)
32
+ this.#serverlessDeliveryTracker?.waitForIdle(done)
14
33
  }
15
34
  }
16
35
 
@@ -33,11 +33,12 @@ class ExternalLogger {
33
33
  }
34
34
 
35
35
  static tagString (tags) {
36
- const tagArray = []
36
+ let tagString = ''
37
37
  for (const key in tags) {
38
- tagArray.push(key + ':' + tags[key])
38
+ if (tagString) tagString += ','
39
+ tagString += key + ':' + tags[key]
39
40
  }
40
- return tagArray.join(',')
41
+ return tagString
41
42
  }
42
43
 
43
44
  // Parses and enqueues a log
@@ -0,0 +1,105 @@
1
+ 'use strict'
2
+
3
+ const log = require('./log')
4
+ const { supportsServerlessTelemetryRetention } = require('./serverless')
5
+
6
+ /**
7
+ * @typedef {(done: () => void) => void} TelemetryFlusher
8
+ */
9
+
10
+ /** @type {Set<TelemetryFlusher>} */
11
+ const telemetryFlushers = new Set()
12
+ const postTraceTelemetryFlushers = new Set()
13
+
14
+ /**
15
+ * @typedef {{
16
+ * trace?: TelemetryFlusher,
17
+ * spanStats?: TelemetryFlusher
18
+ * }} TraceFlushers
19
+ */
20
+
21
+ /**
22
+ * Registers a configured telemetry pipeline so serverless lifecycle retention
23
+ * waits for its final export alongside trace delivery.
24
+ * @param {TelemetryFlusher} flusher
25
+ * @param {{ afterTrace?: boolean }} [options]
26
+ * @returns {() => void} Removes this pipeline when its provider is replaced.
27
+ */
28
+ function registerTelemetryFlusher (flusher, options) {
29
+ if (!supportsServerlessTelemetryRetention()) return () => {}
30
+
31
+ const flushers = options?.afterTrace ? postTraceTelemetryFlushers : telemetryFlushers
32
+ flushers.add(flusher)
33
+ // Avoid retaining a replaced provider or flushing it alongside the new one.
34
+ return () => flushers.delete(flusher)
35
+ }
36
+
37
+ /**
38
+ * Coordinates the configured telemetry flushers for a serverless lifecycle.
39
+ *
40
+ * Trace-owned flushers are supplied by DatadogTracer so this module does not
41
+ * depend on its private implementation details.
42
+ * @param {() => void} [done]
43
+ * @param {{ timeout?: number }} [options]
44
+ * @param {TraceFlushers} [traceFlushers]
45
+ */
46
+ function flushServerlessTelemetry (done, options, traceFlushers) {
47
+ const traceFlusher = traceFlushers?.trace
48
+ const spanStatsFlusher = traceFlushers?.spanStats
49
+ // TODO: Include DSM after DataStreamsProcessor exposes a completion-aware flush API.
50
+ let pending = telemetryFlushers.size + postTraceTelemetryFlushers.size +
51
+ (typeof traceFlusher === 'function' ? 1 : 0) +
52
+ (typeof spanStatsFlusher === 'function' ? 1 : 0)
53
+
54
+ if (pending === 0) return done?.()
55
+
56
+ let completed = false
57
+ let timeout
58
+
59
+ const finish = () => {
60
+ if (completed) return
61
+ completed = true
62
+ clearTimeout(timeout)
63
+ done?.()
64
+ }
65
+ const complete = () => {
66
+ if (--pending === 0) finish()
67
+ }
68
+
69
+ if (options?.timeout) {
70
+ timeout = setTimeout(() => {
71
+ log.warn('Timed out waiting for telemetry flush after %dms', options.timeout)
72
+ finish()
73
+ }, options.timeout)
74
+ }
75
+
76
+ const flush = (flusher, afterFlushed) => {
77
+ let flushed = false
78
+ const onFlushed = error => {
79
+ if (flushed) return
80
+ flushed = true
81
+ if (error) log.error('Error flushing telemetry pipeline:', error)
82
+ afterFlushed?.()
83
+ complete()
84
+ }
85
+ try {
86
+ flusher(onFlushed)
87
+ } catch (error) {
88
+ onFlushed(error)
89
+ }
90
+ }
91
+
92
+ if (typeof traceFlusher === 'function') {
93
+ flush(traceFlusher, () => {
94
+ for (const flusher of postTraceTelemetryFlushers) flush(flusher)
95
+ })
96
+ } else {
97
+ for (const flusher of postTraceTelemetryFlushers) flush(flusher)
98
+ }
99
+ if (typeof spanStatsFlusher === 'function') {
100
+ flush(spanStatsFlusher)
101
+ }
102
+ for (const flusher of telemetryFlushers) flush(flusher)
103
+ }
104
+
105
+ module.exports = { flushServerlessTelemetry, registerTelemetryFlusher }
@@ -2,6 +2,8 @@
2
2
 
3
3
  const { randomFillSync } = require('crypto')
4
4
 
5
+ const { channel } = require('dc-polyfill')
6
+
5
7
  const UINT_MAX = 4_294_967_296
6
8
 
7
9
  const data = new Uint8Array(8 * 8192)
@@ -9,6 +11,8 @@ const zeroId = new Uint8Array(8)
9
11
 
10
12
  let batch = 0
11
13
 
14
+ channel('datadog:identity:update').subscribe(reseed)
15
+
12
16
  // Internal representation of a trace or span ID.
13
17
  class Identifier {
14
18
  /** @type {number[] | Uint8Array} */
@@ -254,6 +258,16 @@ function writeUInt32BE (buffer, value, offset) {
254
258
  buffer[0 + offset] = value & 255
255
259
  }
256
260
 
261
+ /**
262
+ * Resets the batch cursor, forcing the next ID batch to draw a fresh
263
+ * randomFillSync() call on MicroVM clone resume. Node's crypto RNG is
264
+ * re-seeded from the kernel CSPRNG on snapshot resume, so re-invoking it
265
+ * is sufficient — no need to read /dev/urandom directly.
266
+ */
267
+ function reseed () {
268
+ batch = 0
269
+ }
270
+
257
271
  /**
258
272
  * @param {string} [value]
259
273
  * @param {number} [radix]
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
- const { getValueFromEnvSources } = require('./config/helper')
3
+ const { getEnvironmentVariable, getValueFromEnvSources } = require('./config/helper')
4
+ const { isTrue } = require('./util')
4
5
 
5
6
  // Global `jest` is only present in Jest workers.
6
7
  const inJestWorker = typeof jest !== 'undefined'
@@ -8,8 +9,10 @@ const inJestWorker = typeof jest !== 'undefined'
8
9
  // skipDefault: distinguish an unset DD_TRACE_ENABLED (fall back to the OTel signal) from an
9
10
  // explicit value; the registered default would otherwise mask the OTEL_TRACES_EXPORTER check.
10
11
  const ddTraceEnabled = getValueFromEnvSources('DD_TRACE_ENABLED', true)
12
+ const agentlessTracingEnabled = getValueFromEnvSources('DD_AGENTLESS_ENABLED') ||
13
+ isTrue(getEnvironmentVariable('_DD_APM_TRACING_AGENTLESS_ENABLED'))
11
14
  const ddTraceDisabled = ddTraceEnabled === undefined
12
- ? getValueFromEnvSources('OTEL_TRACES_EXPORTER') === 'none'
15
+ ? !agentlessTracingEnabled && getValueFromEnvSources('OTEL_TRACES_EXPORTER') === 'none'
13
16
  : ddTraceEnabled === false
14
17
 
15
18
  module.exports = ddTraceDisabled || inJestWorker
@@ -108,6 +108,10 @@ class ExperimentsClient {
108
108
  return this.#site
109
109
  }
110
110
 
111
+ get projectName () {
112
+ return this.#projectName
113
+ }
114
+
111
115
  // Dashboard URL base for the configured site, e.g. https://app.datadoghq.com
112
116
  get appBase () {
113
117
  return `https://${appHost(this.#site)}`
@@ -1,8 +1,18 @@
1
1
  'use strict'
2
2
 
3
3
  const { randomUUID } = require('node:crypto')
4
+ const createRfdc = require('../../../../../vendor/dist/rfdc')
5
+ const snapshotPayload = createRfdc({ proto: false, circles: false })
4
6
 
5
7
  /** @typedef {{add?: string[], remove?: string[], replace?: string[]}} TagOperations */
8
+ /**
9
+ * @typedef {object} DatasetRecordNew
10
+ * @property {string} [id]
11
+ * @property {unknown} inputData
12
+ * @property {unknown} [expectedOutput]
13
+ * @property {Record<string, unknown>} [metadata]
14
+ * @property {string[]} [tags]
15
+ */
6
16
  /**
7
17
  * @typedef {object} PendingBatch
8
18
  * @property {object} attributes
@@ -114,6 +124,9 @@ function updateFromInsertedRecord (recordId, record, payload) {
114
124
  update.expectedOutput = record.expectedOutput
115
125
  }
116
126
  if (!valuesAreEqual(record.metadata, payload.metadata)) update.metadata = record.metadata
127
+ if (!valuesAreEqual(record.tags, payload.tags ?? [])) {
128
+ update.tagOperations = { replace: [...record.tags] }
129
+ }
117
130
  return update
118
131
  }
119
132
 
@@ -173,6 +186,36 @@ class Dataset {
173
186
  return this
174
187
  }
175
188
 
189
+ /**
190
+ * Add multiple records to a dataset.
191
+ * @param {DatasetRecordNew[]} records
192
+ * @returns {Dataset} This dataset for chaining.
193
+ */
194
+ addRecords (records) {
195
+ const newRecords = []
196
+ const recordIds = new Set(this.#recordsById.keys())
197
+
198
+ // Construct and validate the entire batch before mutating the dataset.
199
+ for (const record of records) {
200
+ if (record.id !== undefined && (typeof record.id !== 'string' || record.id.length === 0)) {
201
+ throw new Error('record id must be a non-empty string')
202
+ }
203
+ const newRecord = new DatasetRecord(
204
+ record.inputData,
205
+ record.expectedOutput,
206
+ record.metadata,
207
+ record.id,
208
+ record.tags
209
+ )
210
+ if (recordIds.has(newRecord.id)) throw new Error(`Duplicate record id '${newRecord.id}'`)
211
+ recordIds.add(newRecord.id)
212
+ newRecords.push(newRecord)
213
+ }
214
+
215
+ for (const record of newRecords) this.#addRecord(record)
216
+ return this
217
+ }
218
+
176
219
  /**
177
220
  * Add tags to a dataset record.
178
221
  * @param {number} index Dataset record index.
@@ -336,6 +379,10 @@ class Dataset {
336
379
  return this.#projectId
337
380
  }
338
381
 
382
+ projectName () {
383
+ return this.#client.projectName
384
+ }
385
+
339
386
  version () {
340
387
  return this.#version
341
388
  }
@@ -416,7 +463,7 @@ class Dataset {
416
463
  const insertRecords = []
417
464
  const insertPayloads = new Map()
418
465
  for (const [recordId, record] of this.#newRecordsById) {
419
- const payload = serializedRecord(record)
466
+ const payload = snapshotPayload(serializedRecord(record))
420
467
  insertRecords.push(payload)
421
468
  insertPayloads.set(recordId, payload)
422
469
  }
@@ -427,7 +474,7 @@ class Dataset {
427
474
  const tagOperations = this.#pendingTagOperations.get(recordId)
428
475
  if (tagOperations) update.tagOperations = tagOperations
429
476
  else delete update.tagOperations
430
- const payload = serializedRecordUpdate(update)
477
+ const payload = snapshotPayload(serializedRecordUpdate(update))
431
478
  updateRecords.push(payload)
432
479
  updatePayloads.set(recordId, payload)
433
480
  }
@@ -522,6 +569,9 @@ class Dataset {
522
569
  updateFromInsertedRecord(recordId, current, payload)
523
570
  const queuedOperations = this.#pendingTagOperations.get(recordId)
524
571
  if (queuedOperations) update.tagOperations = queuedOperations
572
+ if (update.tagOperations) {
573
+ this.#pendingTagOperations.set(recordId, copyTagOperations(update.tagOperations))
574
+ }
525
575
  this.#updatedRecordsById.set(recordId, update)
526
576
  }
527
577