dd-trace 6.16.0 → 6.18.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 (356) hide show
  1. package/ci/diagnose.js +0 -23
  2. package/ci/test-optimization-validation/approval-artifacts.js +0 -3
  3. package/ci/test-optimization-validation/approval.js +0 -6
  4. package/ci/test-optimization-validation/artifact-id.js +0 -1
  5. package/ci/test-optimization-validation/bounded-json.js +0 -1
  6. package/ci/test-optimization-validation/cli.js +0 -12
  7. package/ci/test-optimization-validation/command-output-policy.js +0 -1
  8. package/ci/test-optimization-validation/command-runner.js +0 -3
  9. package/ci/test-optimization-validation/environment.js +0 -4
  10. package/ci/test-optimization-validation/executable-approval.js +0 -1
  11. package/ci/test-optimization-validation/executable.js +0 -5
  12. package/ci/test-optimization-validation/framework-adapters/cucumber.js +0 -6
  13. package/ci/test-optimization-validation/framework-adapters/cypress.js +0 -3
  14. package/ci/test-optimization-validation/framework-adapters/playwright.js +0 -6
  15. package/ci/test-optimization-validation/framework-adapters/vitest.js +0 -4
  16. package/ci/test-optimization-validation/generated-test-contract.js +0 -5
  17. package/ci/test-optimization-validation/generated-verifier.js +0 -1
  18. package/ci/test-optimization-validation/literal-environment.js +0 -1
  19. package/ci/test-optimization-validation/manifest-scaffold.js +0 -17
  20. package/ci/test-optimization-validation/manifest-schema.js +0 -21
  21. package/ci/test-optimization-validation/offline-fixtures.js +0 -4
  22. package/ci/test-optimization-validation/plan-writer.js +0 -11
  23. package/ci/test-optimization-validation/preflight-runner.js +0 -1
  24. package/ci/test-optimization-validation/redaction.js +0 -4
  25. package/ci/test-optimization-validation/report-writer.js +0 -16
  26. package/ci/test-optimization-validation/runner-command.js +0 -3
  27. package/ci/test-optimization-validation/runner-contract.js +0 -4
  28. package/ci/test-optimization-validation/safe-files.js +0 -1
  29. package/ci/test-optimization-validation/scenarios/basic-reporting.js +0 -1
  30. package/ci/test-optimization-validation/scenarios/ci-wiring.js +0 -1
  31. package/ci/test-optimization-validation/source-text.js +0 -3
  32. package/ci/vitest-no-worker-init-setup.mjs +41 -16
  33. package/index.d.ts +208 -0
  34. package/package.json +17 -16
  35. package/packages/datadog-esbuild/src/utils.js +0 -2
  36. package/packages/datadog-instrumentations/src/aerospike.js +28 -6
  37. package/packages/datadog-instrumentations/src/aws-durable-execution-sdk-js.js +0 -2
  38. package/packages/datadog-instrumentations/src/aws-sdk.js +0 -2
  39. package/packages/datadog-instrumentations/src/claude-agent-sdk.js +0 -2
  40. package/packages/datadog-instrumentations/src/console.js +97 -0
  41. package/packages/datadog-instrumentations/src/cucumber.js +77 -12
  42. package/packages/datadog-instrumentations/src/cypress-config.js +27 -38
  43. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +6 -0
  44. package/packages/datadog-instrumentations/src/helpers/channel.js +0 -2
  45. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -1
  46. package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +0 -5
  47. package/packages/datadog-instrumentations/src/helpers/hooks.js +8 -6
  48. package/packages/datadog-instrumentations/src/helpers/instrumentation-utils.js +0 -3
  49. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +0 -6
  50. package/packages/datadog-instrumentations/src/helpers/register.js +24 -0
  51. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +111 -26
  52. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +41 -0
  53. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +3 -17
  54. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +55 -0
  55. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +36 -0
  56. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/supabase.js +128 -0
  57. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/webdriverio.js +13 -0
  58. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.js +28 -3
  59. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +20 -0
  60. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +388 -0
  61. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +0 -5
  62. package/packages/datadog-instrumentations/src/helpers/router-helper.js +0 -1
  63. package/packages/datadog-instrumentations/src/jest.js +165 -51
  64. package/packages/datadog-instrumentations/src/knex.js +0 -1
  65. package/packages/datadog-instrumentations/src/mariadb-bundle.js +0 -24
  66. package/packages/datadog-instrumentations/src/mariadb.js +0 -2
  67. package/packages/datadog-instrumentations/src/mocha/common.js +0 -1
  68. package/packages/datadog-instrumentations/src/mocha/main.js +25 -26
  69. package/packages/datadog-instrumentations/src/mocha/utils.js +119 -49
  70. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +0 -6
  71. package/packages/datadog-instrumentations/src/mocha/worker.js +14 -17
  72. package/packages/datadog-instrumentations/src/mysql2.js +0 -2
  73. package/packages/datadog-instrumentations/src/openai-realtime/audio-accumulator.js +241 -0
  74. package/packages/datadog-instrumentations/src/openai-realtime/events.js +76 -0
  75. package/packages/datadog-instrumentations/src/openai-realtime/index.js +301 -0
  76. package/packages/datadog-instrumentations/src/openai-realtime/session.js +998 -0
  77. package/packages/datadog-instrumentations/src/openai-realtime/turns.js +211 -0
  78. package/packages/datadog-instrumentations/src/openai.js +51 -12
  79. package/packages/datadog-instrumentations/src/oracledb.js +9 -3
  80. package/packages/datadog-instrumentations/src/playwright-reporter.js +6 -20
  81. package/packages/datadog-instrumentations/src/playwright.js +280 -56
  82. package/packages/datadog-instrumentations/src/{azure-cosmos.js → postgres.js} +1 -1
  83. package/packages/datadog-instrumentations/src/router.js +0 -2
  84. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +0 -2
  85. package/packages/datadog-instrumentations/src/sequelize.js +0 -1
  86. package/packages/datadog-instrumentations/src/supabase.js +15 -0
  87. package/packages/datadog-instrumentations/src/undici.js +7 -3
  88. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +18 -18
  89. package/packages/datadog-instrumentations/src/vitest-main.js +121 -30
  90. package/packages/datadog-instrumentations/src/vitest-util.js +7 -1
  91. package/packages/datadog-instrumentations/src/vitest-worker.js +49 -13
  92. package/packages/datadog-instrumentations/src/webdriverio.js +44 -47
  93. package/packages/datadog-instrumentations/src/ws.js +41 -2
  94. package/packages/datadog-plugin-ai/src/utils.js +0 -2
  95. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +0 -1
  96. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +0 -2
  97. package/packages/datadog-plugin-aws-sdk/src/base.js +0 -1
  98. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +0 -1
  99. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +0 -1
  100. package/packages/datadog-plugin-aws-sdk/src/util.js +0 -1
  101. package/packages/datadog-plugin-azure-durable-functions/src/index.js +0 -1
  102. package/packages/datadog-plugin-cucumber/src/index.js +9 -0
  103. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +211 -85
  104. package/packages/datadog-plugin-cypress/src/finalization.js +0 -3
  105. package/packages/datadog-plugin-cypress/src/index.js +3 -1
  106. package/packages/datadog-plugin-cypress/src/source-map-utils.js +0 -4
  107. package/packages/datadog-plugin-cypress/src/support.js +52 -7
  108. package/packages/datadog-plugin-graphql/src/resolve-error.js +1 -2
  109. package/packages/datadog-plugin-graphql/src/utils.js +0 -5
  110. package/packages/datadog-plugin-jest/src/index.js +12 -0
  111. package/packages/datadog-plugin-kafkajs/src/producer.js +0 -1
  112. package/packages/datadog-plugin-mocha/src/index.js +38 -11
  113. package/packages/datadog-plugin-mongodb-core/src/query.js +0 -1
  114. package/packages/datadog-plugin-openai/src/index.js +16 -1
  115. package/packages/datadog-plugin-openai/src/realtime.js +144 -0
  116. package/packages/datadog-plugin-openai-agents/src/integration.js +0 -4
  117. package/packages/datadog-plugin-openai-agents/src/util.js +0 -1
  118. package/packages/datadog-plugin-playwright/src/index.js +81 -9
  119. package/packages/datadog-plugin-postgres/src/index.js +167 -0
  120. package/packages/datadog-plugin-prisma/src/datadog-tracing-helper.js +0 -1
  121. package/packages/datadog-plugin-redis/src/index.js +15 -1
  122. package/packages/datadog-plugin-supabase/src/error.js +18 -0
  123. package/packages/datadog-plugin-supabase/src/index.js +21 -0
  124. package/packages/datadog-plugin-supabase/src/supabase-auth-js-gotrueclient-getuser.js +69 -0
  125. package/packages/datadog-plugin-supabase/src/supabase-functions-js-functionsclient-invoke.js +70 -0
  126. package/packages/datadog-plugin-supabase/src/supabase-postgrest-js-postgrestbuilder-then.js +122 -0
  127. package/packages/datadog-plugin-supabase/src/supabase-realtime-js-realtimechannel-send.js +66 -0
  128. package/packages/datadog-plugin-supabase/src/supabase-storage-js-handle-request.js +93 -0
  129. package/packages/datadog-plugin-supabase/src/url.js +17 -0
  130. package/packages/datadog-plugin-vitest/src/index.js +9 -0
  131. package/packages/datadog-plugin-ws/src/producer.js +1 -1
  132. package/packages/datadog-plugin-ws/src/util.js +0 -4
  133. package/packages/datadog-shimmer/src/shimmer.js +14 -10
  134. package/packages/datadog-turbopack/index.js +4 -7
  135. package/packages/datadog-turbopack/src/loader.js +6 -18
  136. package/packages/datadog-webpack/src/loader.js +0 -1
  137. package/packages/dd-trace/src/agent/info.js +5 -4
  138. package/packages/dd-trace/src/aiguard/client.js +2 -3
  139. package/packages/dd-trace/src/aiguard/evaluation.js +6 -12
  140. package/packages/dd-trace/src/aiguard/index.js +2 -2
  141. package/packages/dd-trace/src/aiguard/integrations/index.js +1 -1
  142. package/packages/dd-trace/src/aiguard/integrations/openai.js +81 -7
  143. package/packages/dd-trace/src/aiguard/messages/anthropic.js +0 -2
  144. package/packages/dd-trace/src/aiguard/messages/openai.js +64 -1
  145. package/packages/dd-trace/src/aiguard/messages/utils.js +0 -1
  146. package/packages/dd-trace/src/aiguard/redaction.js +0 -1
  147. package/packages/dd-trace/src/aiguard/sdk.js +1 -1
  148. package/packages/dd-trace/src/appsec/activation.js +1 -1
  149. package/packages/dd-trace/src/appsec/api_security/normalized-route.js +0 -5
  150. package/packages/dd-trace/src/appsec/api_security/sampler.js +0 -4
  151. package/packages/dd-trace/src/appsec/blocking/index.js +3 -3
  152. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -4
  153. package/packages/dd-trace/src/appsec/iast/index.js +1 -1
  154. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +5 -5
  155. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +1 -1
  156. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  157. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +3 -3
  158. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +8 -10
  159. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -2
  160. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +4 -1
  161. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +7 -7
  162. package/packages/dd-trace/src/appsec/index.js +2 -2
  163. package/packages/dd-trace/src/appsec/lambda.js +71 -2
  164. package/packages/dd-trace/src/appsec/rasp/utils.js +5 -1
  165. package/packages/dd-trace/src/appsec/remote_config.js +8 -6
  166. package/packages/dd-trace/src/appsec/reporter.js +10 -6
  167. package/packages/dd-trace/src/appsec/rule_manager.js +3 -3
  168. package/packages/dd-trace/src/appsec/sdk/track_event.js +0 -2
  169. package/packages/dd-trace/src/appsec/waf/index.js +2 -2
  170. package/packages/dd-trace/src/appsec/waf/waf_manager.js +8 -5
  171. package/packages/dd-trace/src/carrier.js +0 -5
  172. package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +104 -0
  173. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +0 -2
  174. package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +34 -3
  175. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +0 -1
  176. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +0 -1
  177. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +0 -1
  178. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +0 -4
  179. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +0 -1
  180. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +0 -2
  181. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +37 -15
  182. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +0 -3
  183. package/packages/dd-trace/src/ci-visibility/exporters/request.js +0 -11
  184. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +0 -1
  185. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +0 -1
  186. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +0 -6
  187. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -2
  188. package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +0 -1
  189. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +0 -5
  190. package/packages/dd-trace/src/ci-visibility/requests/video-request.js +0 -1
  191. package/packages/dd-trace/src/ci-visibility/telemetry.js +13 -0
  192. package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +0 -1
  193. package/packages/dd-trace/src/ci-visibility/test-screenshot.js +0 -2
  194. package/packages/dd-trace/src/ci-visibility/test-video.js +0 -1
  195. package/packages/dd-trace/src/config/defaults.js +3 -2
  196. package/packages/dd-trace/src/config/generated-config-types.d.ts +88 -82
  197. package/packages/dd-trace/src/config/helper.js +0 -1
  198. package/packages/dd-trace/src/config/index.js +31 -30
  199. package/packages/dd-trace/src/config/parsers.js +34 -6
  200. package/packages/dd-trace/src/config/remote_config.js +25 -109
  201. package/packages/dd-trace/src/config/supported-configurations.json +150 -10
  202. package/packages/dd-trace/src/datastreams/encoding.js +0 -1
  203. package/packages/dd-trace/src/datastreams/pathway.js +0 -1
  204. package/packages/dd-trace/src/debugger/constants.js +10 -0
  205. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +62 -10
  206. package/packages/dd-trace/src/debugger/devtools_client/config.js +4 -1
  207. package/packages/dd-trace/src/debugger/devtools_client/guardrail-metrics.js +15 -0
  208. package/packages/dd-trace/src/debugger/devtools_client/index.js +103 -27
  209. package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +50 -7
  210. package/packages/dd-trace/src/debugger/devtools_client/log.js +3 -1
  211. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +21 -8
  212. package/packages/dd-trace/src/debugger/devtools_client/send.js +41 -15
  213. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +53 -13
  214. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +118 -71
  215. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +5 -3
  216. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +0 -3
  217. package/packages/dd-trace/src/debugger/devtools_client/status.js +21 -7
  218. package/packages/dd-trace/src/debugger/guardrail-metrics.js +167 -0
  219. package/packages/dd-trace/src/debugger/index.js +51 -3
  220. package/packages/dd-trace/src/debugger/inspect-segment.js +0 -3
  221. package/packages/dd-trace/src/debugger/probe_sampler.js +133 -9
  222. package/packages/dd-trace/src/debugger/probe_sampler_constants.js +31 -1
  223. package/packages/dd-trace/src/dogstatsd.js +0 -23
  224. package/packages/dd-trace/src/encode/0.4-cross-payload.js +0 -3
  225. package/packages/dd-trace/src/encode/0.4.js +0 -7
  226. package/packages/dd-trace/src/encode/0.5.js +0 -2
  227. package/packages/dd-trace/src/encode/tags-processors.js +0 -1
  228. package/packages/dd-trace/src/evp_proxy/constants.js +2 -0
  229. package/packages/dd-trace/src/evp_proxy/direct.js +17 -13
  230. package/packages/dd-trace/src/evp_proxy/discovery.js +14 -11
  231. package/packages/dd-trace/src/evp_proxy/path.js +21 -9
  232. package/packages/dd-trace/src/exporters/agent/writer.js +0 -1
  233. package/packages/dd-trace/src/exporters/agentless/index.js +0 -1
  234. package/packages/dd-trace/src/exporters/agentless/intake.js +0 -1
  235. package/packages/dd-trace/src/exporters/agentless/writer.js +0 -3
  236. package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +0 -6
  237. package/packages/dd-trace/src/exporters/common/request.js +1 -0
  238. package/packages/dd-trace/src/exporters/common/url.js +33 -4
  239. package/packages/dd-trace/src/exporters/common/writer.js +0 -2
  240. package/packages/dd-trace/src/id.js +0 -11
  241. package/packages/dd-trace/src/llmobs/audio-codec.js +192 -0
  242. package/packages/dd-trace/src/llmobs/audio-utils.js +121 -0
  243. package/packages/dd-trace/src/llmobs/constants/audio.js +35 -0
  244. package/packages/dd-trace/src/llmobs/constants/prompts.js +14 -0
  245. package/packages/dd-trace/src/llmobs/constants/tags.js +17 -0
  246. package/packages/dd-trace/src/llmobs/eval-metric.js +0 -6
  247. package/packages/dd-trace/src/llmobs/experiments/dataset.js +0 -4
  248. package/packages/dd-trace/src/llmobs/experiments/experiment.js +0 -3
  249. package/packages/dd-trace/src/llmobs/experiments/index.js +7 -6
  250. package/packages/dd-trace/src/llmobs/experiments/util.js +1 -11
  251. package/packages/dd-trace/src/llmobs/index.js +1 -3
  252. package/packages/dd-trace/src/llmobs/noop.js +10 -0
  253. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +0 -4
  254. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +0 -1
  255. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +0 -4
  256. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +0 -2
  257. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +0 -2
  258. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +4 -6
  259. package/packages/dd-trace/src/llmobs/plugins/openai/realtime.js +285 -0
  260. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +16 -3
  261. package/packages/dd-trace/src/llmobs/prompts/cache.js +272 -0
  262. package/packages/dd-trace/src/llmobs/prompts/manager.js +647 -0
  263. package/packages/dd-trace/src/llmobs/prompts/noop.js +29 -0
  264. package/packages/dd-trace/src/llmobs/prompts/prompt.js +158 -0
  265. package/packages/dd-trace/src/llmobs/sdk.js +21 -6
  266. package/packages/dd-trace/src/llmobs/span_processor.js +81 -2
  267. package/packages/dd-trace/src/llmobs/tagger.js +39 -11
  268. package/packages/dd-trace/src/llmobs/telemetry.js +36 -4
  269. package/packages/dd-trace/src/llmobs/util.js +0 -34
  270. package/packages/dd-trace/src/llmobs/writers/base.js +0 -1
  271. package/packages/dd-trace/src/llmobs/writers/util.js +1 -2
  272. package/packages/dd-trace/src/log/channels.js +3 -0
  273. package/packages/dd-trace/src/log/index.js +23 -5
  274. package/packages/dd-trace/src/log-submission/log-submission-plugin.js +74 -6
  275. package/packages/dd-trace/src/msgpack/chunk.js +0 -1
  276. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +0 -12
  277. package/packages/dd-trace/src/openfeature/configuration_source.js +4 -1
  278. package/packages/dd-trace/src/openfeature/encoding.js +0 -2
  279. package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +0 -1
  280. package/packages/dd-trace/src/openfeature/flagging_provider.js +3 -3
  281. package/packages/dd-trace/src/openfeature/index.js +6 -6
  282. package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +0 -1
  283. package/packages/dd-trace/src/openfeature/span-enrichment.js +0 -4
  284. package/packages/dd-trace/src/openfeature/writers/base.js +90 -23
  285. package/packages/dd-trace/src/openfeature/writers/exposures.js +4 -5
  286. package/packages/dd-trace/src/openfeature/writers/util.js +104 -37
  287. package/packages/dd-trace/src/opentelemetry/logs/logger.js +0 -1
  288. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +0 -1
  289. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +0 -1
  290. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +0 -2
  291. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +0 -1
  292. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +0 -1
  293. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +0 -1
  294. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -14
  295. package/packages/dd-trace/src/opentelemetry/metrics/time.js +0 -1
  296. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +30 -13
  297. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +0 -1
  298. package/packages/dd-trace/src/opentelemetry/span-helpers.js +0 -1
  299. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +0 -1
  300. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +0 -3
  301. package/packages/dd-trace/src/opentracing/propagation/text_map.js +0 -6
  302. package/packages/dd-trace/src/opentracing/span_context.js +0 -1
  303. package/packages/dd-trace/src/opentracing/tracer.js +3 -3
  304. package/packages/dd-trace/src/otel-thread-ctx.js +38 -11
  305. package/packages/dd-trace/src/payload-tagging/tagging.js +15 -3
  306. package/packages/dd-trace/src/plugin_manager.js +27 -8
  307. package/packages/dd-trace/src/plugins/ci_plugin.js +1 -2
  308. package/packages/dd-trace/src/plugins/database.js +2 -6
  309. package/packages/dd-trace/src/plugins/index.js +7 -0
  310. package/packages/dd-trace/src/plugins/plugin.js +0 -4
  311. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  312. package/packages/dd-trace/src/plugins/util/git.js +1 -3
  313. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +0 -1
  314. package/packages/dd-trace/src/plugins/util/llm.js +0 -2
  315. package/packages/dd-trace/src/plugins/util/status-validator.js +0 -1
  316. package/packages/dd-trace/src/plugins/util/test.js +26 -20
  317. package/packages/dd-trace/src/plugins/util/url.js +0 -5
  318. package/packages/dd-trace/src/priority_sampler.js +0 -6
  319. package/packages/dd-trace/src/process-tags/index.js +0 -1
  320. package/packages/dd-trace/src/profiler.js +132 -35
  321. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +0 -1
  322. package/packages/dd-trace/src/profiling/profiler.js +101 -41
  323. package/packages/dd-trace/src/profiling/ssi-heuristics.js +29 -15
  324. package/packages/dd-trace/src/propagation-hash/index.js +0 -1
  325. package/packages/dd-trace/src/proxy.js +23 -47
  326. package/packages/dd-trace/src/random_sampler.js +0 -4
  327. package/packages/dd-trace/src/rate_limiter.js +0 -4
  328. package/packages/dd-trace/src/remote_config/capabilities.js +1 -9
  329. package/packages/dd-trace/src/remote_config/index.js +0 -1
  330. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +0 -3
  331. package/packages/dd-trace/src/sampler.js +0 -4
  332. package/packages/dd-trace/src/sampling_rule.js +0 -7
  333. package/packages/dd-trace/src/serverless/vercel.js +0 -1
  334. package/packages/dd-trace/src/serverless.js +0 -1
  335. package/packages/dd-trace/src/service-naming/index.js +0 -1
  336. package/packages/dd-trace/src/service-naming/schemas/util.js +0 -1
  337. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +7 -0
  338. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +5 -0
  339. package/packages/dd-trace/src/span_processor.js +2 -2
  340. package/packages/dd-trace/src/span_sampler.js +0 -1
  341. package/packages/dd-trace/src/standalone/product.js +2 -2
  342. package/packages/dd-trace/src/standalone/tracesource.js +0 -1
  343. package/packages/dd-trace/src/startup-log.js +1 -1
  344. package/packages/dd-trace/src/telemetry/endpoints.js +0 -8
  345. package/packages/dd-trace/src/telemetry/logs/index.js +16 -5
  346. package/packages/dd-trace/src/telemetry/logs/log-collector.js +16 -6
  347. package/packages/dd-trace/src/telemetry/metrics.js +0 -2
  348. package/packages/dd-trace/src/telemetry/send-data.js +2 -1
  349. package/packages/dd-trace/src/telemetry/telemetry.js +4 -1
  350. package/packages/dd-trace/src/tracer.js +5 -4
  351. package/packages/dd-trace/src/util.js +13 -1
  352. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
  353. package/packages/datadog-instrumentations/src/bullmq.js +0 -11
  354. package/packages/datadog-instrumentations/src/langchain.js +0 -7
  355. package/packages/datadog-instrumentations/src/langgraph.js +0 -7
  356. package/packages/datadog-instrumentations/src/mercurius.js +0 -11
@@ -0,0 +1,192 @@
1
+ 'use strict'
2
+
3
+ // Raw-audio primitives shared by the LLM Observability integrations: mapping provider audio formats
4
+ // to MIME types, decoding telephony audio to PCM16, wrapping PCM16 in a WAV container, and deriving
5
+ // a segment's playback duration from its byte count. Deliberately free of LLM Observability concepts
6
+ // so the realtime instrumentation can use the timing half without pulling in span plumbing.
7
+
8
+ const { G711_SAMPLE_RATE, PCM16_BYTES_PER_SAMPLE, WAV_HEADER_BYTES } = require('./constants/audio')
9
+
10
+ // OpenAI Realtime audio `format` values (legacy string form) that don't map to `audio/<format>`.
11
+ // A Map rather than an object literal so a hostile format string ("constructor", "__proto__") can't
12
+ // resolve to something off Object.prototype.
13
+ const REALTIME_FORMAT_MIME_TYPES = new Map([
14
+ ['pcm16', 'audio/pcm'],
15
+ ['pcm', 'audio/pcm'],
16
+ ['g711_ulaw', 'audio/pcmu'],
17
+ ['g711_alaw', 'audio/pcma'],
18
+ ])
19
+
20
+ // Raw little-endian PCM16. Not renderable on its own, but losslessly wrappable in a WAV container.
21
+ const PCM16_MIME_TYPES = new Set(['audio/pcm', 'audio/pcm16', 'audio/l16'])
22
+
23
+ // G.711 telephony audio (8 kHz, 8-bit companded), used by Realtime for phone-call integrations.
24
+ const G711_MIME_TO_VARIANT = new Map([
25
+ ['audio/pcmu', 'ulaw'],
26
+ ['audio/g711_ulaw', 'ulaw'],
27
+ ['audio/pcma', 'alaw'],
28
+ ['audio/g711_alaw', 'alaw'],
29
+ ])
30
+
31
+ /**
32
+ * Decode one G.711 mu-law byte to a signed 16-bit linear PCM sample (CCITT G.711).
33
+ *
34
+ * @param {number} byte
35
+ */
36
+ function decodeUlawSample (byte) {
37
+ byte = ~byte & 0xFF
38
+ let sample = ((byte & 0x0F) << 3) + 0x84
39
+ sample <<= (byte & 0x70) >> 4
40
+ return (byte & 0x80) ? (0x84 - sample) : (sample - 0x84)
41
+ }
42
+
43
+ /**
44
+ * Decode one G.711 A-law byte to a signed 16-bit linear PCM sample (CCITT G.711).
45
+ *
46
+ * @param {number} byte
47
+ */
48
+ function decodeAlawSample (byte) {
49
+ byte ^= 0x55
50
+ let sample = (byte & 0x0F) << 4
51
+ const segment = (byte & 0x70) >> 4
52
+ if (segment === 0) {
53
+ sample += 8
54
+ } else if (segment === 1) {
55
+ sample += 0x1_08
56
+ } else {
57
+ sample = (sample + 0x1_08) << (segment - 1)
58
+ }
59
+ return (byte & 0x80) ? sample : -sample
60
+ }
61
+
62
+ // The input domain is a single byte, so both decodes collapse to a 256-entry lookup built once.
63
+ const ULAW_TABLE = new Int16Array(256)
64
+ const ALAW_TABLE = new Int16Array(256)
65
+ for (let byte = 0; byte < 256; byte++) {
66
+ ULAW_TABLE[byte] = decodeUlawSample(byte)
67
+ ALAW_TABLE[byte] = decodeAlawSample(byte)
68
+ }
69
+
70
+ /**
71
+ * Map an OpenAI Realtime audio format to a MIME type.
72
+ *
73
+ * Handles both the legacy string form (e.g. "pcm16", "g711_ulaw") and the newer discriminated-union
74
+ * object whose `type` is already a MIME type (e.g. "audio/pcm"). Yields an empty string when the
75
+ * format is absent or unusable, which callers treat as "unknown" rather than guessing a rate.
76
+ *
77
+ * @param {string | { type?: string } | undefined} format
78
+ */
79
+ function realtimeAudioFormatToMime (format) {
80
+ const type = typeof format === 'object' && format !== null ? format.type : format
81
+ if (typeof type !== 'string') return ''
82
+
83
+ const normalized = type.trim().toLowerCase()
84
+ if (!normalized) return ''
85
+ if (normalized.startsWith('audio/')) return normalized
86
+
87
+ return REALTIME_FORMAT_MIME_TYPES.get(normalized) ?? `audio/${normalized}`
88
+ }
89
+
90
+ /**
91
+ * @param {string} mimeType
92
+ */
93
+ function isPcm16AudioMime (mimeType) {
94
+ return typeof mimeType === 'string' && PCM16_MIME_TYPES.has(mimeType.trim().toLowerCase())
95
+ }
96
+
97
+ /**
98
+ * @param {string} mimeType
99
+ * @returns {'ulaw' | 'alaw' | undefined} The G.711 variant, or `undefined` for any other format.
100
+ */
101
+ function g711Variant (mimeType) {
102
+ if (typeof mimeType !== 'string') return
103
+ return G711_MIME_TO_VARIANT.get(mimeType.trim().toLowerCase())
104
+ }
105
+
106
+ /**
107
+ * Decode G.711 audio to raw little-endian PCM16.
108
+ *
109
+ * @param {Buffer} data
110
+ * @param {'ulaw' | 'alaw'} variant
111
+ * @returns {Buffer}
112
+ */
113
+ function g711ToPcm16 (data, variant) {
114
+ const table = variant === 'alaw' ? ALAW_TABLE : ULAW_TABLE
115
+ const pcm = Buffer.allocUnsafe(data.length * PCM16_BYTES_PER_SAMPLE)
116
+ for (let i = 0; i < data.length; i++) {
117
+ pcm.writeInt16LE(table[data[i]], i * PCM16_BYTES_PER_SAMPLE)
118
+ }
119
+ return pcm
120
+ }
121
+
122
+ /**
123
+ * Wrap raw little-endian PCM16 audio in a WAV container.
124
+ *
125
+ * Lossless and cheap — it only prepends a 44-byte header — and turns raw PCM, which the UI can't
126
+ * render, into a playable `audio/wav` payload.
127
+ *
128
+ * @param {Buffer} pcm
129
+ * @param {number} [sampleRate]
130
+ * @param {number} [channels]
131
+ * @returns {Buffer}
132
+ */
133
+ function pcm16ToWav (pcm, sampleRate = 24_000, channels = 1) {
134
+ const blockAlign = channels * PCM16_BYTES_PER_SAMPLE
135
+ const header = Buffer.allocUnsafe(WAV_HEADER_BYTES)
136
+
137
+ header.write('RIFF', 0, 'latin1')
138
+ header.writeUInt32LE(WAV_HEADER_BYTES - 8 + pcm.length, 4) // RIFF chunk size: everything after this field
139
+ header.write('WAVE', 8, 'latin1')
140
+ header.write('fmt ', 12, 'latin1')
141
+ header.writeUInt32LE(16, 16) // fmt chunk size, 16 for PCM
142
+ header.writeUInt16LE(1, 20) // audio format, 1 for uncompressed PCM
143
+ header.writeUInt16LE(channels, 22)
144
+ header.writeUInt32LE(sampleRate, 24)
145
+ header.writeUInt32LE(sampleRate * blockAlign, 28) // byte rate
146
+ header.writeUInt16LE(blockAlign, 32)
147
+ header.writeUInt16LE(PCM16_BYTES_PER_SAMPLE * 8, 34) // bits per sample
148
+ header.write('data', 36, 'latin1')
149
+ header.writeUInt32LE(pcm.length, 40)
150
+
151
+ return Buffer.concat([header, pcm], WAV_HEADER_BYTES + pcm.length)
152
+ }
153
+
154
+ /**
155
+ * Byte rate of a raw audio format: PCM16 is 2 bytes per sample at the session's rate, G.711 is 1
156
+ * byte per sample at the fixed 8 kHz rate. Any other or unknown format returns `undefined` — we do
157
+ * not guess a rate, so durations and offsets derived from it are simply unavailable.
158
+ *
159
+ * @param {string} mimeType
160
+ * @param {number} sampleRate
161
+ * @returns {number | undefined}
162
+ */
163
+ function bytesPerSecond (mimeType, sampleRate) {
164
+ if (sampleRate > 0 && isPcm16AudioMime(mimeType)) return sampleRate * PCM16_BYTES_PER_SAMPLE
165
+ if (g711Variant(mimeType) !== undefined) return G711_SAMPLE_RATE
166
+ }
167
+
168
+ /**
169
+ * Playback duration (in milliseconds) of an audio segment, from its decoded byte count. Sizes the
170
+ * user-speech and agent-speech spans and the turn root's end, so it may be fractional.
171
+ *
172
+ * @param {number} decodedBytes
173
+ * @param {string} mimeType
174
+ * @param {number} sampleRate
175
+ * @returns {number | undefined}
176
+ */
177
+ function segmentDurationMs (decodedBytes, mimeType, sampleRate) {
178
+ if (!(decodedBytes > 0)) return
179
+ const rate = bytesPerSecond(mimeType, sampleRate)
180
+ if (!rate) return
181
+ return decodedBytes / rate * 1000
182
+ }
183
+
184
+ module.exports = {
185
+ bytesPerSecond,
186
+ g711ToPcm16,
187
+ g711Variant,
188
+ isPcm16AudioMime,
189
+ pcm16ToWav,
190
+ realtimeAudioFormatToMime,
191
+ segmentDurationMs,
192
+ }
@@ -0,0 +1,121 @@
1
+ 'use strict'
2
+
3
+ // Building `audioPart`s for LLM Observability messages: mapping provider audio formats to MIME
4
+ // types, and keeping inline audio within the per-span-event size budget. The raw-audio primitives
5
+ // these build on (WAV wrapping, G.711 decoding, byte rates) live in `audio-codec.js`.
6
+
7
+ const log = require('../log')
8
+ const { LLMOBS_AUDIO_INLINE_MAX_BYTES } = require('./constants/audio')
9
+
10
+ /**
11
+ * @typedef {{ mimeType: string, content: string }} AudioPart
12
+ */
13
+
14
+ // Raw audio formats the UI cannot render as a player. For these we keep the transcript as the
15
+ // message content and skip the inline audio part, since raw bytes would only bloat the payload.
16
+ const NON_RENDERABLE_AUDIO_MIME_TYPES = new Set([
17
+ 'audio/pcm',
18
+ 'audio/pcm16',
19
+ 'audio/l16',
20
+ 'audio/pcmu',
21
+ 'audio/pcma',
22
+ 'audio/g711_ulaw',
23
+ 'audio/g711_alaw',
24
+ 'audio/basic',
25
+ ])
26
+
27
+ /**
28
+ * Length of `byteLength` bytes after standard base64 encoding: 4 characters per 3 bytes, padded.
29
+ *
30
+ * @param {number} byteLength
31
+ */
32
+ function base64EncodedLength (byteLength) {
33
+ return Math.ceil(byteLength / 3) * 4
34
+ }
35
+
36
+ // Maps an audio `format` (e.g. "wav", "mp3") to a MIME type. Defaults to `audio/wav` when the
37
+ // format is missing. Provider-specific overrides (e.g. OpenAI's mp3 -> audio/mpeg) are passed in
38
+ // via `mimeTypeLookup` so this stays provider-agnostic. A non-string `format` is treated as missing
39
+ // so a malformed auto-instrumented payload can't throw and disable the plugin.
40
+ /**
41
+ * @param {string} fmt
42
+ * @param {Record<string, string>} [mimeTypeLookup]
43
+ */
44
+ function audioMimeTypeFromFormat (fmt, mimeTypeLookup = {}) {
45
+ fmt = typeof fmt === 'string' ? fmt.trim().toLowerCase() : ''
46
+ if (!fmt) return 'audio/wav'
47
+ // `hasOwn` rather than a plain lookup: a format of "constructor" would otherwise resolve to
48
+ // something off Object.prototype and be returned as the MIME type.
49
+ return Object.hasOwn(mimeTypeLookup, fmt) ? mimeTypeLookup[fmt] : `audio/${fmt}`
50
+ }
51
+
52
+ /**
53
+ * Whether a MIME type can be rendered as an audio player in the UI. Raw PCM cannot.
54
+ *
55
+ * @param {string} mimeType
56
+ */
57
+ function isRenderableAudioMime (mimeType) {
58
+ return typeof mimeType === 'string' &&
59
+ mimeType.length > 0 &&
60
+ !NON_RENDERABLE_AUDIO_MIME_TYPES.has(mimeType.trim().toLowerCase())
61
+ }
62
+
63
+ // Builds an audio part from raw audio bytes (base64-encoded) or an existing base64 string. Only
64
+ // Buffer/Uint8Array inputs are base64-encoded; any other shape is passed through so a malformed
65
+ // auto-instrumented payload can't throw (the tagger soft-skips a non-string `content`).
66
+ /**
67
+ * @param {Buffer | Uint8Array | string} data
68
+ * @param {string} mimeType
69
+ * @returns {AudioPart}
70
+ */
71
+ function formatAudioPart (data, mimeType) {
72
+ const content = Buffer.isBuffer(data) || ArrayBuffer.isView(data)
73
+ ? Buffer.from(data).toString('base64')
74
+ : data
75
+ return { mimeType, content }
76
+ }
77
+
78
+ /**
79
+ * Whether `byteLength` bytes of audio fit the inline budget once base64-encoded.
80
+ *
81
+ * Compares the *encoded* size: `formatAudioPart` base64-encodes the bytes (~4/3 expansion), and it
82
+ * is that encoded content which counts against the per-span-event limit. Exposed separately so a
83
+ * caller that has to allocate to produce those bytes — decoding G.711 to PCM16, wrapping raw PCM in
84
+ * a WAV container — can check the size it is about to produce before paying for it.
85
+ *
86
+ * @param {number} byteLength
87
+ * @param {number} [maxBytes]
88
+ */
89
+ function fitsInlineAudioBudget (byteLength, maxBytes = LLMOBS_AUDIO_INLINE_MAX_BYTES) {
90
+ const encodedLength = base64EncodedLength(byteLength)
91
+ if (encodedLength <= maxBytes) return true
92
+
93
+ log.debug('Audio (%d encoded bytes) exceeds inline budget %d; omitting inline audio content',
94
+ encodedLength, maxBytes)
95
+ return false
96
+ }
97
+
98
+ /**
99
+ * Build a playable audio part, but only for renderable formats within the size budget. Returns
100
+ * `undefined` for a non-renderable format (e.g. raw PCM) or oversize audio; callers fall back to the
101
+ * transcript as the message content in that case.
102
+ *
103
+ * @param {Buffer} audioBytes
104
+ * @param {string} mimeType
105
+ * @param {number} [maxBytes]
106
+ * @returns {AudioPart | undefined}
107
+ */
108
+ function formatAudioPartWithGuard (audioBytes, mimeType, maxBytes = LLMOBS_AUDIO_INLINE_MAX_BYTES) {
109
+ if (!audioBytes?.length || !isRenderableAudioMime(mimeType)) return
110
+ if (!fitsInlineAudioBudget(audioBytes.length, maxBytes)) return
111
+
112
+ return formatAudioPart(audioBytes, mimeType)
113
+ }
114
+
115
+ module.exports = {
116
+ audioMimeTypeFromFormat,
117
+ fitsInlineAudioBudget,
118
+ formatAudioPart,
119
+ formatAudioPartWithGuard,
120
+ isRenderableAudioMime,
121
+ }
@@ -0,0 +1,35 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ // Surfaced as a message's content when audio was captured but couldn't be turned into a playable
5
+ // part (unsupported format, or over the size budget) and there is no transcript to show instead.
6
+ AUDIO_FALLBACK: '[audio]',
7
+
8
+ // G.711 telephony audio is always 8 kHz mono.
9
+ G711_SAMPLE_RATE: 8000,
10
+
11
+ // Budget for inline audio, measured on the *base64-encoded* size, since that is what actually
12
+ // rides the span event. Kept below the 5 MB per-span-event limit with headroom for the rest of the
13
+ // event, whose whole I/O is dropped backend-side when oversize. 4 MiB encoded is ~3 MiB of audio.
14
+ //
15
+ // Per *event*, not per audio part. An event carrying audio on more than one message — a realtime
16
+ // turn has both the user's and the agent's — has to divide this between them, or two individually
17
+ // accepted clips sum past the limit and cost the event all of its I/O.
18
+ LLMOBS_AUDIO_INLINE_MAX_BYTES: 4 * 1024 * 1024,
19
+
20
+ // Cap on the raw audio buffered per side of a realtime turn: the point at which base64 encoding
21
+ // would put a 1:1 format over `LLMOBS_AUDIO_INLINE_MAX_BYTES` anyway (4 chars per 3 bytes).
22
+ // Beyond this the size guard would drop the audio at tag time, so we stop retaining it rather
23
+ // than hold megabytes in memory only to discard them. A memory bound, not a correctness one — the
24
+ // guard still decides.
25
+ //
26
+ // A format that expands on the way to a playable part inlines less than this: G.711 decodes to
27
+ // PCM16 at 2 bytes per sample, so only about half of it can ever ride the span event. Callers
28
+ // check the *converted* size against the budget before converting (`fitsInlineAudioBudget`), so
29
+ // the excess is never paid for in allocations — it is only retained and then dropped.
30
+ LLMOBS_AUDIO_ACCUMULATE_MAX_BYTES: 3 * 1024 * 1024,
31
+
32
+ PCM16_BYTES_PER_SAMPLE: 2,
33
+
34
+ WAV_HEADER_BYTES: 44,
35
+ }
@@ -0,0 +1,14 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ ERROR_NAMES: {
5
+ API: 'PromptAPIError',
6
+ AUTH: 'PromptAuthError',
7
+ CONFLICT: 'PromptConflictError',
8
+ NOT_FOUND: 'PromptNotFoundError',
9
+ SERVER: 'PromptServerError',
10
+ VALIDATION: 'PromptValidationError',
11
+ },
12
+ PROMPTS_PATH: '/api/unstable/llm-obs/v1/prompts',
13
+ SOURCE_CACHE: 'cache',
14
+ }
@@ -69,6 +69,23 @@ module.exports = {
69
69
  INSTRUMENTATION_METHOD_ANNOTATED: 'annotated',
70
70
  INSTRUMENTATION_METHOD_UNKNOWN: 'unknown',
71
71
 
72
+ GEN_AI_OPERATION_NAME: 'gen_ai.operation.name',
73
+ GEN_AI_REQUEST_MODEL: 'gen_ai.request.model',
74
+ GEN_AI_PROVIDER_NAME: 'gen_ai.provider.name',
75
+ GEN_AI_APPLICATION_NAME: 'gen_ai.application.name',
76
+ GEN_AI_CONVERSATION_ID: 'gen_ai.conversation.id',
77
+
78
+ GEN_AI_USAGE_INPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.input_tokens',
79
+ GEN_AI_USAGE_OUTPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.output_tokens',
80
+ GEN_AI_USAGE_TOTAL_TOKENS_METRIC_KEY: 'gen_ai.usage.total_tokens',
81
+ GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.cache_read_input_tokens',
82
+ GEN_AI_USAGE_CACHE_WRITE_INPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.cache_write_input_tokens',
83
+ GEN_AI_USAGE_REASONING_OUTPUT_TOKENS_METRIC_KEY: 'gen_ai.usage.reasoning_output_tokens',
84
+
85
+ // Marks the `gen_ai.*` tags on an APM span as tracer-emitted. Without it the backend reads them
86
+ // as user-set and builds a duplicate LLMObs span out of the APM span.
87
+ ARTIFICIAL_GEN_AI_TAGS: '_dd.llmobs.artificial_gen_ai_tags',
88
+
72
89
  ROUTING_API_KEY: '_dd.llmobs.routing.api_key',
73
90
  ROUTING_SITE: '_dd.llmobs.routing.site',
74
91
  }
@@ -61,7 +61,6 @@ const TERMS = {
61
61
 
62
62
  /**
63
63
  * @param {string[]} metricTypes
64
- * @returns {string} the quoted list, e.g. `"categorical", "score" or "json"`
65
64
  */
66
65
  function formatMetricTypes (metricTypes) {
67
66
  const quoted = metricTypes.map(metricType => `"${metricType}"`)
@@ -99,7 +98,6 @@ function invalidTagsError (kind) {
99
98
  /**
100
99
  * @param {unknown} timestampMs
101
100
  * @param {MetricEventKind} kind
102
- * @returns {void}
103
101
  */
104
102
  function validateTimestamp (timestampMs, kind) {
105
103
  if (typeof timestampMs !== 'number' || timestampMs < 0) {
@@ -137,7 +135,6 @@ function validateLabel (label, kind) {
137
135
  /**
138
136
  * @param {string | undefined} metricType - Already lower-cased metric type.
139
137
  * @param {MetricEventKind} kind
140
- * @returns {void}
141
138
  */
142
139
  function validateMetricType (metricType, kind) {
143
140
  if (!metricType || !METRIC_TYPES[kind].includes(metricType)) {
@@ -148,7 +145,6 @@ function validateMetricType (metricType, kind) {
148
145
  /**
149
146
  * @param {string | undefined} metricType - Metric type already validated for the submitted kind.
150
147
  * @param {unknown} value
151
- * @returns {void}
152
148
  */
153
149
  function validateMetricValue (metricType, value) {
154
150
  if (metricType === 'categorical' && typeof value !== 'string') {
@@ -170,7 +166,6 @@ function validateMetricValue (metricType, value) {
170
166
 
171
167
  /**
172
168
  * @param {unknown} assessment
173
- * @returns {void}
174
169
  */
175
170
  function validateAssessment (assessment) {
176
171
  if (assessment != null && assessment !== 'pass' && assessment !== 'fail') {
@@ -180,7 +175,6 @@ function validateAssessment (assessment) {
180
175
 
181
176
  /**
182
177
  * @param {unknown} reasoning
183
- * @returns {void}
184
178
  */
185
179
  function validateReasoning (reasoning) {
186
180
  if (reasoning != null && typeof reasoning !== 'string') {
@@ -330,7 +330,6 @@ class Dataset {
330
330
  * @param {string} recordId Dataset record id.
331
331
  * @param {'add' | 'remove' | 'replace'} operation Tag operation to queue.
332
332
  * @param {string[]} tags Tags in key:value format.
333
- * @returns {void}
334
333
  */
335
334
  #queueTagOperation (recordId, operation, tags) {
336
335
  if (operation !== 'replace' && tags.length === 0) return
@@ -503,7 +502,6 @@ class Dataset {
503
502
  * Detach tag changes sent by this batch so edits made while the request is in flight
504
503
  * are queued relative to the response that this batch will commit.
505
504
  * @param {PendingBatch} pending
506
- * @returns {void}
507
505
  */
508
506
  #detachCommittedTagOperations (pending) {
509
507
  pending.inFlightTagOperations = new Map()
@@ -527,7 +525,6 @@ class Dataset {
527
525
  /**
528
526
  * Restore tag changes when a batch request fails, including edits made while it was in flight.
529
527
  * @param {PendingBatch} pending
530
- * @returns {void}
531
528
  */
532
529
  #restoreFailedTagOperations (pending) {
533
530
  if (!pending.inFlightTagOperations) return
@@ -549,7 +546,6 @@ class Dataset {
549
546
  /**
550
547
  * Clear the changes represented by a completed batch while retaining concurrent local edits.
551
548
  * @param {PendingBatch} pending
552
- * @returns {void}
553
549
  */
554
550
  #clearCommittedChanges (pending) {
555
551
  for (const [recordId, payload] of pending.insertPayloads) {
@@ -1015,9 +1015,6 @@ class ExternalExperiment {
1015
1015
  this.#experiment = experiment
1016
1016
  }
1017
1017
 
1018
- /**
1019
- * @returns {string}
1020
- */
1021
1018
  name () {
1022
1019
  return this.#experiment.name()
1023
1020
  }
@@ -35,8 +35,8 @@ class Experiments {
35
35
 
36
36
  constructor (config, llmobs) {
37
37
  this.#config = config
38
- this.#llmobs = config.llmobs?.mlApp || config.service ? llmobs : undefined
39
- this.#projectName = config.llmobs?.projectName || DEFAULT_PROJECT_NAME
38
+ this.#llmobs = config.llmobs?.DD_LLMOBS_ML_APP || config.service ? llmobs : undefined
39
+ this.#projectName = config.llmobs?.DD_LLMOBS_PROJECT_NAME || DEFAULT_PROJECT_NAME
40
40
  this.#client = this.#clientForProject(this.#projectName)
41
41
  }
42
42
 
@@ -179,9 +179,9 @@ class Experiments {
179
179
  const projectName = options?.projectName ?? datasetProjectName
180
180
  const client = this.#clientForOperation(projectName)
181
181
  const usesDatasetOverride = datasetProjectName !== undefined && datasetProjectName !== this.#projectName
182
- const resolvedProjectName = projectName ?? this.#config.llmobs?.projectName
182
+ const resolvedProjectName = projectName ?? this.#config.llmobs?.DD_LLMOBS_PROJECT_NAME
183
183
  const experimentOptions = options?.projectName === undefined &&
184
- (usesDatasetOverride || this.#config.llmobs?.projectName !== undefined) &&
184
+ (usesDatasetOverride || this.#config.llmobs?.DD_LLMOBS_PROJECT_NAME !== undefined) &&
185
185
  resolvedProjectName !== undefined
186
186
  ? { ...options, projectName: resolvedProjectName }
187
187
  : options
@@ -198,8 +198,9 @@ class Experiments {
198
198
  */
199
199
  startExperiment (options) {
200
200
  const client = this.#clientForOperation(options?.projectName)
201
- const experimentOptions = options?.projectName === undefined && this.#config.llmobs?.projectName !== undefined
202
- ? { ...options, projectName: this.#config.llmobs.projectName }
201
+ const experimentOptions = options?.projectName === undefined &&
202
+ this.#config.llmobs?.DD_LLMOBS_PROJECT_NAME !== undefined
203
+ ? { ...options, projectName: this.#config.llmobs.DD_LLMOBS_PROJECT_NAME }
203
204
  : options
204
205
  return new Experiment(client, { ...experimentOptions, external: true }).start()
205
206
  .then(experiment => new ExternalExperiment(experiment))
@@ -14,7 +14,6 @@ const EVALUATOR_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/
14
14
 
15
15
  /**
16
16
  * @param {object | null | undefined} value
17
- * @returns {boolean}
18
17
  */
19
18
  function hasEntries (value) {
20
19
  if (!value) return false
@@ -47,16 +46,12 @@ function tagOperationsAreEmpty (operations) {
47
46
  /**
48
47
  * @param {unknown} value
49
48
  * @param {string} name
50
- * @returns {number}
51
49
  */
52
50
  function normalizePositiveInteger (value, name) {
53
51
  if (!Number.isInteger(value) || value < 1) throw new Error(`${name} must be a positive integer`)
54
- return value
52
+ return /** @type {number} */ (value)
55
53
  }
56
54
 
57
- /**
58
- * @returns {string}
59
- */
60
55
  function generateRunId () {
61
56
  return randomUUID()
62
57
  }
@@ -77,7 +72,6 @@ function validateEvaluatorName (name) {
77
72
  /**
78
73
  * @param {(...args: unknown[]) => unknown} fn
79
74
  * @param {string} fallback
80
- * @returns {string}
81
75
  */
82
76
  function functionName (fn, fallback) {
83
77
  return typeof fn.name === 'string' && fn.name.length > 0 ? fn.name : fallback
@@ -124,7 +118,6 @@ function normalizeEvaluators (evaluators, kind) {
124
118
 
125
119
  /**
126
120
  * @param {unknown} value
127
- * @returns {string}
128
121
  */
129
122
  function inferMetricType (value) {
130
123
  if (typeof value === 'boolean') return 'boolean'
@@ -184,7 +177,6 @@ function normalizeJsonMetricValue (value) {
184
177
 
185
178
  /**
186
179
  * @param {unknown} value
187
- * @returns {string}
188
180
  */
189
181
  function stringify (value) {
190
182
  if (value == null) return ''
@@ -270,7 +262,6 @@ function sleep (ms) {
270
262
  /**
271
263
  * @param {unknown} value
272
264
  * @param {number} fallback
273
- * @returns {number}
274
265
  */
275
266
  function timestampMs (value, fallback = Date.now()) {
276
267
  if (value === null || value === undefined) return fallback
@@ -286,7 +277,6 @@ function timestampMs (value, fallback = Date.now()) {
286
277
  /**
287
278
  * @param {{ durationMs?: unknown, completedAt?: unknown }} row
288
279
  * @param {number} startMs
289
- * @returns {number}
290
280
  */
291
281
  function durationNs (row, startMs) {
292
282
  if (typeof row.durationMs === 'number' && Number.isFinite(row.durationMs)) {
@@ -152,7 +152,6 @@ function disable () {
152
152
  * Keeps retired writers reachable until their destroy-triggered deliveries complete.
153
153
  * @param {LLMObsSpanWriter | null} retiredSpanWriter
154
154
  * @param {LLMObsEvalMetricsWriter | null} retiredEvalWriter
155
- * @returns {void}
156
155
  */
157
156
  function retireWriters (retiredSpanWriter, retiredEvalWriter) {
158
157
  const retiredWriters = [retiredSpanWriter, retiredEvalWriter].filter(Boolean)
@@ -183,7 +182,7 @@ function handleLLMObsInjection (injection) {
183
182
  const mlApp =
184
183
  mlObsSpanTags?.[ML_APP] ||
185
184
  parentContext?._trace?.tags?.[PROPAGATED_ML_APP_KEY] ||
186
- globalTracerConfig.llmobs.mlApp
185
+ globalTracerConfig.llmobs.DD_LLMOBS_ML_APP
187
186
 
188
187
  const sampleRate =
189
188
  mlObsSpanTags?.[SAMPLE_RATE] ?? parentContext?._trace?.tags?.[PROPAGATED_SAMPLE_RATE_KEY]
@@ -239,7 +238,6 @@ function handleLLMObsInjection (injection) {
239
238
  * @param {Function} [done]
240
239
  * @param {LLMObsSpanWriter | null} [currentSpanWriter]
241
240
  * @param {LLMObsEvalMetricsWriter | null} [currentEvalWriter]
242
- * @returns {boolean} `true` when a writer throws synchronously.
243
241
  */
244
242
  function flushWriters (done, currentSpanWriter = spanWriter, currentEvalWriter = evalWriter) {
245
243
  let failed = false
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
 
3
+ const NoopPrompts = require('./prompts/noop')
4
+
3
5
  let NoopExperiments
4
6
 
5
7
  class NoopLLMObs {
@@ -16,6 +18,14 @@ class NoopLLMObs {
16
18
  return new NoopExperiments('LLM Observability is not enabled')
17
19
  }
18
20
 
21
+ /**
22
+ * Prompt Management API.
23
+ * @returns {import('../../../../index').llmobs.Prompts}
24
+ */
25
+ get prompts () {
26
+ return new NoopPrompts()
27
+ }
28
+
19
29
  enable (options) {}
20
30
 
21
31
  disable () {}
@@ -337,7 +337,6 @@ function getToolNameFromTags (tags) {
337
337
 
338
338
  /**
339
339
  * @param {unknown} value
340
- * @returns {string}
341
340
  */
342
341
  function stringifyToolCallResult (value) {
343
342
  return JSON.stringify(value) ?? UNPARSABLE_TOOL_RESULT
@@ -345,7 +344,6 @@ function stringifyToolCallResult (value) {
345
344
 
346
345
  /**
347
346
  * @param {ToolCallContentPart[]} value
348
- * @returns {string}
349
347
  */
350
348
  function formatToolCallContent (value) {
351
349
  if (!Array.isArray(value)) return UNPARSABLE_TOOL_RESULT
@@ -388,7 +386,6 @@ function formatToolCallContent (value) {
388
386
 
389
387
  /**
390
388
  * @param {ToolCallResultContent | null | undefined} content
391
- * @returns {string}
392
389
  */
393
390
  function getToolCallResultContent (content) {
394
391
  try {
@@ -426,7 +423,6 @@ function getToolCallResultContent (content) {
426
423
  * Computes the LLM Observability `ai` span name
427
424
  * @param {string} operation
428
425
  * @param {string} functionId
429
- * @returns {string}
430
426
  */
431
427
  function getLlmObsSpanName (operation, functionId) {
432
428
  return functionId ? `${functionId}.${operation}` : operation
@@ -62,7 +62,6 @@ function formatAnthropicToolResultContent (content) {
62
62
  *
63
63
  * @param {AnthropicLlmObsMessage[]} messages
64
64
  * @param {{ role: string, content: string | Array<TextBlock | ImageBlock | ToolUseBlock | ToolResultBlock> }} message
65
- * @returns {void}
66
65
  */
67
66
  function appendMessage (messages, { role, content }) {
68
67
  if (typeof content === 'string') {