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
@@ -102,6 +102,7 @@ const TEST_STATUS = 'test.status'
102
102
  const TEST_FINAL_STATUS = 'test.final_status'
103
103
  const TEST_PARAMETERS = 'test.parameters'
104
104
  const TEST_SKIP_REASON = 'test.skip_reason'
105
+ const TEST_SESSION_EMPTY_REASON = 'test.session.empty_reason'
105
106
  const TEST_IS_RUM_ACTIVE = 'test.is_rum_active'
106
107
  const TEST_CODE_OWNERS = 'test.codeowners'
107
108
  const TEST_SOURCE_FILE = 'test.source.file'
@@ -445,7 +446,6 @@ function addTestOptimizationRequest (requestPromises, responseNames, responseNam
445
446
  *
446
447
  * @param {string} testSuite
447
448
  * @param {string|undefined} testSuiteExecutionId
448
- * @returns {string}
449
449
  */
450
450
  function getTestSuiteExecutionKey (testSuite, testSuiteExecutionId) {
451
451
  return testSuiteExecutionId ? `${testSuite}\0${testSuiteExecutionId}` : testSuite
@@ -471,9 +471,11 @@ module.exports = {
471
471
  TEST_FINAL_STATUS,
472
472
  TEST_PARAMETERS,
473
473
  TEST_SKIP_REASON,
474
+ TEST_SESSION_EMPTY_REASON,
474
475
  TEST_IS_RUM_ACTIVE,
475
476
  setRumTestCorrelation,
476
477
  setRumTestTags,
478
+ setExpectedEmptyTestSessionTags,
477
479
  TEST_SOURCE_FILE,
478
480
  TEST_FAILURE_SCREENSHOT_UPLOADED,
479
481
  TEST_FAILURE_SCREENSHOT_UPLOAD_ERROR,
@@ -868,7 +870,6 @@ function finishAllTraceSpans (span) {
868
870
  * @param {import('../../opentracing/span')} testSpan
869
871
  * @param {boolean|undefined} isRumActive
870
872
  * @param {string} [browserVersion]
871
- * @returns {void}
872
873
  */
873
874
  function setRumTestTags (testSpan, isRumActive, browserVersion) {
874
875
  if (isRumActive) {
@@ -879,6 +880,29 @@ function setRumTestTags (testSpan, isRumActive, browserVersion) {
879
880
  }
880
881
  }
881
882
 
883
+ /**
884
+ * Marks a successful test session that did not execute any tests.
885
+ *
886
+ * @param {import('../../opentracing/span')} testSessionSpan
887
+ * @param {import('../../opentracing/span')|undefined} testModuleSpan
888
+ * @param {'zero_tests'|'all_tests_skipped'|'zero_test_shard'|'test_discovery'} emptyReason
889
+ */
890
+ function setExpectedEmptyTestSessionTags (testSessionSpan, testModuleSpan, emptyReason) {
891
+ const skipReason = emptyReason === 'test_discovery'
892
+ ? 'Test discovery only (--list)'
893
+ : emptyReason === 'zero_test_shard'
894
+ ? 'No tests were assigned to this shard'
895
+ : emptyReason === 'all_tests_skipped' ? 'All tests were skipped' : 'No tests were detected'
896
+
897
+ for (const span of [testSessionSpan, testModuleSpan]) {
898
+ if (!span) continue
899
+
900
+ span.setTag(TEST_STATUS, 'skip')
901
+ span.setTag(TEST_SKIP_REASON, skipReason)
902
+ span.setTag(TEST_SESSION_EMPTY_REASON, emptyReason)
903
+ }
904
+ }
905
+
882
906
  /**
883
907
  * @param {RumTestCorrelationContext} context
884
908
  * @param {import('../../opentracing/span')|undefined} activeSpan
@@ -942,7 +966,6 @@ function getTestCommonTags (name, suite, version, testFramework) {
942
966
  *
943
967
  * @param {string | undefined} testSuiteAbsolutePath
944
968
  * @param {string} sourceRoot
945
- * @returns {string}
946
969
  */
947
970
  function getTestSuitePath (testSuiteAbsolutePath, sourceRoot) {
948
971
  if (!testSuiteAbsolutePath) {
@@ -1069,7 +1092,6 @@ const codeOwnersPerEntries = new WeakMap()
1069
1092
 
1070
1093
  /**
1071
1094
  * @param {string} character
1072
- * @returns {string}
1073
1095
  */
1074
1096
  function escapeRegexCharacter (character) {
1075
1097
  return character.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw`\$&`)
@@ -1077,7 +1099,6 @@ function escapeRegexCharacter (character) {
1077
1099
 
1078
1100
  /**
1079
1101
  * @param {string} pattern
1080
- * @returns {boolean}
1081
1102
  */
1082
1103
  function hasUnescapedWildcard (pattern) {
1083
1104
  for (let i = 0; i < pattern.length; i++) {
@@ -1093,7 +1114,6 @@ function hasUnescapedWildcard (pattern) {
1093
1114
 
1094
1115
  /**
1095
1116
  * @param {string} pattern
1096
- * @returns {string}
1097
1117
  */
1098
1118
  function codeOwnersPatternToRegexSource (pattern) {
1099
1119
  let source = ''
@@ -1172,7 +1192,6 @@ function setCodeOwnersPatternRegex (entry) {
1172
1192
  *
1173
1193
  * @param {RegExp|null} regex
1174
1194
  * @param {string} filename
1175
- * @returns {boolean}
1176
1195
  */
1177
1196
  function isCodeOwnersPatternMatch (regex, filename) {
1178
1197
  if (!regex || !filename) {
@@ -1551,7 +1570,6 @@ function applySkippedCoverageToFileCoverage (fileCoverage, skippedBitmap) {
1551
1570
  * @param {object} coverage
1552
1571
  * @param {object} skippedCoverage
1553
1572
  * @param {string} [rootDir]
1554
- * @returns {boolean}
1555
1573
  */
1556
1574
  function applySkippedCoverageToCoverage (coverage, skippedCoverage, rootDir) {
1557
1575
  const skippedCoverageByFilename = getSkippedCoverageByFilename(skippedCoverage)
@@ -1616,7 +1634,6 @@ function fromCoverageMapToCoverage (coverageMap) {
1616
1634
 
1617
1635
  /**
1618
1636
  * @param {number} code
1619
- * @returns {boolean}
1620
1637
  */
1621
1638
  function isAsciiDigit (code) {
1622
1639
  return code >= 0x30 && code <= 0x39
@@ -2042,7 +2059,6 @@ function getModifiedFilesFromDiff (diff) {
2042
2059
  *
2043
2060
  * @param {string | undefined} testSuite
2044
2061
  * @param {string} testName
2045
- * @returns {string}
2046
2062
  */
2047
2063
  function getTestOptimizationIdentity (testSuite, testName) {
2048
2064
  return JSON.stringify([testSuite, testName])
@@ -2053,7 +2069,6 @@ function getTestOptimizationIdentity (testSuite, testName) {
2053
2069
  *
2054
2070
  * @param {string | undefined} testSuite
2055
2071
  * @param {string} testName
2056
- * @returns {string}
2057
2072
  */
2058
2073
  function formatTestOptimizationName (testSuite, testName) {
2059
2074
  return testSuite ? `${testSuite} › ${testName}` : testName
@@ -2063,7 +2078,6 @@ function formatTestOptimizationName (testSuite, testName) {
2063
2078
  * Replaces characters that could make one test occupy multiple CI log lines.
2064
2079
  *
2065
2080
  * @param {string} value
2066
- * @returns {string}
2067
2081
  */
2068
2082
  function sanitizeTestOptimizationName (value) {
2069
2083
  return stripVTControlCharacters(value)
@@ -2077,7 +2091,6 @@ function sanitizeTestOptimizationName (value) {
2077
2091
  *
2078
2092
  * @param {string} value
2079
2093
  * @param {number} maxLength
2080
- * @returns {string}
2081
2094
  */
2082
2095
  function truncateTestOptimizationNameStart (value, maxLength) {
2083
2096
  if (value.length <= maxLength) return value
@@ -2093,7 +2106,6 @@ function truncateTestOptimizationNameStart (value, maxLength) {
2093
2106
  *
2094
2107
  * @param {string} value
2095
2108
  * @param {number} maxLength
2096
- * @returns {string}
2097
2109
  */
2098
2110
  function truncateTestOptimizationNameMiddle (value, maxLength) {
2099
2111
  if (value.length <= maxLength) return value
@@ -2112,7 +2124,6 @@ function truncateTestOptimizationNameMiddle (value, maxLength) {
2112
2124
  *
2113
2125
  * @param {string | undefined} testSuite
2114
2126
  * @param {string} testName
2115
- * @returns {string}
2116
2127
  */
2117
2128
  function formatTestOptimizationDisplayName (testSuite, testName) {
2118
2129
  const sanitizedSuite = testSuite ? sanitizeTestOptimizationName(testSuite) : ''
@@ -2136,7 +2147,6 @@ function formatTestOptimizationDisplayName (testSuite, testName) {
2136
2147
  * Renders a bounded bullet list for Test Optimization summaries.
2137
2148
  *
2138
2149
  * @param {Array<{ text: string, suffix?: string }>} items
2139
- * @returns {string}
2140
2150
  */
2141
2151
  function formatTestOptimizationList (items) {
2142
2152
  const shown = items.slice(0, MAX_TEST_OPTIMIZATION_SUMMARY_ITEMS)
@@ -2299,7 +2309,6 @@ function collectAttemptToFixExecutionFromTraceSpan (span, attemptToFixExecutions
2299
2309
  *
2300
2310
  * @param {{ meta?: Record<string, string> }} span
2301
2311
  * @param {TestManagementExecutions} executions
2302
- * @returns {void}
2303
2312
  */
2304
2313
  function collectTestManagementExecutionFromTraceSpan (span, executions) {
2305
2314
  const meta = span.meta
@@ -2405,7 +2414,6 @@ function addAttemptToFixResultLine (lines, result) {
2405
2414
  *
2406
2415
  * @param {AttemptToFixExecutions} attemptToFixExecutions
2407
2416
  * @param {boolean} [includeTestNames]
2408
- * @returns {string}
2409
2417
  */
2410
2418
  function formatAttemptToFixSummary (attemptToFixExecutions, includeTestNames = true) {
2411
2419
  if (attemptToFixExecutions.size === 0) return ''
@@ -2458,7 +2466,6 @@ function formatAttemptToFixSummary (attemptToFixExecutions, includeTestNames = t
2458
2466
  *
2459
2467
  * @param {TestManagementExecutions} executions
2460
2468
  * @param {boolean} [includeTestNames]
2461
- * @returns {string}
2462
2469
  */
2463
2470
  function formatTestManagementSummary (executions, includeTestNames = true) {
2464
2471
  if (executions.size === 0) return ''
@@ -2509,7 +2516,6 @@ function formatTestManagementSummary (executions, includeTestNames = true) {
2509
2516
  * Formats the dynamic-name warning section of the Test Optimization summary.
2510
2517
  *
2511
2518
  * @param {Set<string>} newTestsWithDynamicNames
2512
- * @returns {string}
2513
2519
  */
2514
2520
  function formatDynamicNamesSummary (newTestsWithDynamicNames) {
2515
2521
  if (newTestsWithDynamicNames.size === 0) return ''
@@ -19,7 +19,6 @@ const SPECIAL_CHARACTER_SEGMENT = /[%&'()*+,:=@]/
19
19
  /**
20
20
  * Extract full URL from HTTP request
21
21
  * @param {import('http').IncomingMessage} req
22
- * @returns {string} Full URL
23
22
  */
24
23
  function extractURL (req) {
25
24
  const headers = req.headers
@@ -42,7 +41,6 @@ function getProtocol (req) {
42
41
  *
43
42
  * @param {object} config
44
43
  * @param {string} url
45
- * @returns {string} obfuscated URL
46
44
  */
47
45
  function obfuscateQs (config, url) {
48
46
  const { queryStringObfuscation } = config
@@ -114,7 +112,6 @@ function getQsObfuscator (config) {
114
112
  * @param {string} base `scheme://host[:port]`
115
113
  * @param {string} [pathname] raw request path, may include `?query`
116
114
  * @param {string} strippedUrl `base` + query-stripped path (used when there is no query)
117
- * @returns {string}
118
115
  */
119
116
  function buildClientHttpUrl (config, base, pathname, strippedUrl) {
120
117
  if (pathname?.includes('?')) {
@@ -133,7 +130,6 @@ function buildClientHttpUrl (config, base, pathname, strippedUrl) {
133
130
  * - Cross tracers compatibility
134
131
  *
135
132
  * @param {string} url
136
- * @returns {string} Url path
137
133
  */
138
134
  function extractPathFromUrl (url) {
139
135
  if (!url) return '/'
@@ -146,7 +142,6 @@ function extractPathFromUrl (url) {
146
142
  * Calculate http.endpoint from URL path
147
143
  *
148
144
  * @param {string} url
149
- * @returns {string} The normalized endpoint
150
145
  */
151
146
  function calculateHttpEndpoint (url) {
152
147
  const path = extractPathFromUrl(url)
@@ -86,7 +86,6 @@ class PrioritySampler {
86
86
 
87
87
  /**
88
88
  * @param {DatadogSpan} span
89
- * @returns {boolean} True if the trace should be sampled based on priority.
90
89
  */
91
90
  isSampled (span) {
92
91
  const priority = this._getPriorityFromAuto(span)
@@ -99,7 +98,6 @@ class PrioritySampler {
99
98
  *
100
99
  * @param {DatadogSpan} span
101
100
  * @param {boolean} [auto] - Whether to use automatic sampling if no manual tags are present.
102
- * @returns {void}
103
101
  */
104
102
  sample (span, auto = true) {
105
103
  if (!span) return
@@ -131,7 +129,6 @@ class PrioritySampler {
131
129
  * Updates agent-provided sampling rates keyed by `service:,env:`.
132
130
  *
133
131
  * @param {Record<string, number>} rates
134
- * @returns {void}
135
132
  */
136
133
  update (rates) {
137
134
  const samplers = {}
@@ -151,7 +148,6 @@ class PrioritySampler {
151
148
  * Validates that a sampling priority value is one of the allowed constants.
152
149
  *
153
150
  * @param {SamplingPriority|undefined} samplingPriority
154
- * @returns {boolean}
155
151
  */
156
152
  validate (samplingPriority) {
157
153
  switch (samplingPriority) {
@@ -277,7 +273,6 @@ class PrioritySampler {
277
273
  * records the effective rate on the trace.
278
274
  *
279
275
  * @param {DatadogSpanContext} context
280
- * @returns {boolean}
281
276
  */
282
277
  _isSampledByRateLimit (context) {
283
278
  // TODO: Change underscored properties to private ones.
@@ -316,7 +311,6 @@ class PrioritySampler {
316
311
  * Tags the trace with a decision maker when priority is keep, or removes it otherwise.
317
312
  *
318
313
  * @param {DatadogSpan} span
319
- * @returns {void}
320
314
  */
321
315
  #addDecisionMaker (span) {
322
316
  const context = span.context()
@@ -16,7 +16,6 @@ const ENTRYPOINT_PATH = require.main?.filename || ''
16
16
  * Sanitize a process tag value
17
17
  *
18
18
  * @param {string} value
19
- * @returns {string}
20
19
  */
21
20
  function sanitize (value) {
22
21
  return String(value)
@@ -1,42 +1,139 @@
1
1
  'use strict'
2
2
 
3
- const { profiler } = require('./profiling')
3
+ const dc = require('dc-polyfill')
4
4
 
5
- globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(() => { profiler.stop() })
5
+ const log = require('./log')
6
6
 
7
- module.exports = {
8
- /**
9
- * @param {import('./config/config-base')} config - Tracer configuration
10
- */
11
- start (config) {
7
+ const configUpdateChannel = dc.channel('datadog:config:update')
8
+
9
+ /** @type {import('./profiling/ssi-heuristics').SSIHeuristics | undefined} */
10
+ let activeSSIHeuristics
11
+
12
+ /** @type {import('./profiling') | undefined} */
13
+ let profilingModule
14
+
15
+ function getProfilingModule () {
16
+ profilingModule ??= require('./profiling')
17
+ return profilingModule
18
+ }
19
+
20
+ // The profiling engine can stop itself (e.g. a collection error) without going through stop(), so
21
+ // read its state directly rather than caching a flag that could drift out of sync. Checking
22
+ // `profilingModule` first avoids forcing the profiling engine (and its native crashtracker binding)
23
+ // to load just to read this.
24
+ function isStarted () {
25
+ return profilingModule !== undefined && profilingModule.profiler.enabled
26
+ }
27
+
28
+ /** @type {typeof import('./profiling/ssi-heuristics') | undefined} */
29
+ let ssiHeuristicsModule
30
+
31
+ function getSSIHeuristicsModule () {
32
+ ssiHeuristicsModule ??= require('./profiling/ssi-heuristics')
33
+ return ssiHeuristicsModule
34
+ }
35
+
36
+ function disableSSIHeuristics () {
37
+ if (!activeSSIHeuristics) return
38
+ activeSSIHeuristics.disable()
39
+ activeSSIHeuristics = undefined
40
+ }
41
+
42
+ /**
43
+ * @param {import('./config/config-base')} config - Tracer configuration
44
+ */
45
+ function start (config) {
46
+ try {
12
47
  // Forward the full tracer config to the profiling layer.
13
48
  // Profiling code is responsible for deriving the specific options it needs.
14
- return profiler.start(config)
15
- },
16
-
17
- stop () {
18
- profiler.stop()
19
- },
20
-
21
- /**
22
- * Declares the set of custom label keys that will be used with
23
- * `runWithLabels`.
24
- *
25
- * @param {Iterable<string>} keys - Custom label key names
26
- */
27
- setCustomLabelKeys: (keys) => {
28
- profiler.setCustomLabelKeys(keys)
29
- },
30
-
31
- /**
32
- * Runs a function with custom profiling labels attached to wall profiler samples.
33
- *
34
- * @param {Record<string, string | number>} labels - Custom labels to attach
35
- * @param {function(): T} fn - Function to execute with the labels
36
- * @returns {T} The return value of fn
37
- * @template T
38
- */
39
- runWithLabels: (labels, fn) => {
40
- return profiler.runWithLabels(labels, fn)
41
- },
49
+ return getProfilingModule().profiler.start(config)
50
+ } catch (error) {
51
+ log.error(
52
+ 'Error starting profiler. For troubleshooting tips, see <https://dtdg.co/nodejs-profiler-troubleshooting>',
53
+ error
54
+ )
55
+ return false
56
+ }
57
+ }
58
+
59
+ function stop () {
60
+ // A stop command for a profiler that has never been loaded is already satisfied. Once loaded,
61
+ // always forward it so the profiling layer can also cancel a restart queued during shutdown.
62
+ if (profilingModule === undefined) return
63
+
64
+ try {
65
+ profilingModule.profiler.stop()
66
+ } catch (error) {
67
+ log.error(
68
+ 'Error stopping profiler. For troubleshooting tips, see <https://dtdg.co/nodejs-profiler-troubleshooting>',
69
+ error
70
+ )
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Declares the set of custom label keys that will be used with
76
+ * `runWithLabels`.
77
+ *
78
+ * @param {Iterable<string>} keys - Custom label key names
79
+ */
80
+ function setCustomLabelKeys (keys) {
81
+ getProfilingModule().profiler.setCustomLabelKeys(keys)
42
82
  }
83
+
84
+ /**
85
+ * Runs a function with custom profiling labels attached to wall profiler samples.
86
+ *
87
+ * @param {Record<string, string | number>} labels - Custom labels to attach
88
+ * @param {function(): T} fn - Function to execute with the labels
89
+ * @returns {T} The return value of fn
90
+ * @template T
91
+ */
92
+ function runWithLabels (labels, fn) {
93
+ return getProfilingModule().profiler.runWithLabels(labels, fn)
94
+ }
95
+
96
+ configUpdateChannel.subscribe((config) => {
97
+ const enabled = config.profiling.DD_PROFILING_ENABLED
98
+ if (enabled === 'true') {
99
+ // A non-auto value means the SSI heuristics no longer get a say; disable them so a trigger that
100
+ // fires after this publish can't start the profiler behind this decision's back.
101
+ disableSSIHeuristics()
102
+ // Leave an already-running profiler alone; otherwise an unrelated remote-config publish
103
+ // (e.g. an unrelated sampling-rate change) would restart it on every update.
104
+ if (!isStarted()) start(config)
105
+ } else if (enabled === 'false') {
106
+ disableSSIHeuristics()
107
+ stop()
108
+ } else if (enabled === 'auto') {
109
+ if (!isStarted() && !activeSSIHeuristics) {
110
+ // 'auto' defers the start decision to SSI heuristics. A running profiler already reflects a
111
+ // decision that was made (by SSI or a prior unconditional enablement), so leave it alone
112
+ // rather than stopping and re-enabling it on every subsequent config publication. Also guard
113
+ // against creating another active instance; each SSIHeuristics instance owns listeners and a
114
+ // timer until the heuristic makes its decision or is explicitly disabled.
115
+ const { SSIHeuristics } = getSSIHeuristicsModule()
116
+ const heuristics = new SSIHeuristics(config)
117
+ activeSSIHeuristics = heuristics
118
+ heuristics.start()
119
+ heuristics.onTriggered(() => {
120
+ // Explicit true/false publishes disable the heuristics, so reaching this callback guarantees
121
+ // the latest valid published value is still 'auto'.
122
+ if (!isStarted()) start(config)
123
+ // The heuristic has made its decision, so release all of its listeners and timer before
124
+ // dropping the module-level reference. This does not stop the profiler that was just
125
+ // started; it only tears down the completed heuristic.
126
+ heuristics.disable()
127
+ if (activeSSIHeuristics === heuristics) activeSSIHeuristics = undefined
128
+ })
129
+ }
130
+ } else {
131
+ // Invalid config should preserve the last valid profiling decision, not accidentally behave
132
+ // like 'auto' or crash the customer application.
133
+ log.warn('Unexpected DD_PROFILING_ENABLED value: %o', enabled)
134
+ }
135
+ })
136
+
137
+ globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(stop)
138
+
139
+ module.exports = { isStarted, start, stop, setCustomLabelKeys, runWithLabels }
@@ -15,7 +15,6 @@ const processTags = require('../../process-tags')
15
15
  * profile event.
16
16
  *
17
17
  * @param {string} [enabled] - config.profiling.DD_PROFILING_ENABLED ('true' | 'false' | 'auto')
18
- * @returns {string}
19
18
  */
20
19
  function getActivation (enabled) {
21
20
  if (enabled === 'auto') return 'auto'
@@ -61,9 +61,12 @@ class Profiler extends EventEmitter {
61
61
  #exporters
62
62
  #flushInterval
63
63
  #lastStart
64
+ #pendingStart
64
65
  #profileSeq = 0
65
66
  #profilers
66
67
  #spanFinishListener
68
+ #startFailed = false
69
+ #stopping
67
70
  #systemInfoReport
68
71
  #currentSnapshotTags
69
72
  #timer
@@ -175,48 +178,72 @@ class Profiler extends EventEmitter {
175
178
  */
176
179
  start (config) {
177
180
  if (this.enabled) return true
178
- this.#enabled = true
179
-
180
- const { tags: snapshotTags, exporters, flushInterval, profilers, uploadCompression, systemInfoReport } =
181
- buildProfilingRuntime(config)
182
- this.#config = config
183
- this.#exporters = exporters
184
- this.#flushInterval = flushInterval
185
- this.#profilers = profilers
186
- this.#currentSnapshotTags = snapshotTags
187
- this.#uploadCompression = uploadCompression
188
- this.#systemInfoReport = systemInfoReport
189
- if (this.#customLabelKeys.size > 0) {
190
- this.#applyCustomLabelKeys()
191
- }
192
-
193
- this._setInterval()
194
- // Log errors if the source map finder fails, but don't prevent the rest
195
- // of the profiler from running without source maps.
196
- let mapper
197
- const { setLogger, SourceMapper } = require('@datadog/pprof')
198
- setLogger(pprofLogger)
199
-
200
- if (config.DD_PROFILING_SOURCE_MAP) {
201
- mapper = new SourceMapper(config.DD_PROFILING_DEBUG_SOURCE_MAPS)
202
- mapper.loadDirectory(process.cwd())
203
- .then(() => {
204
- if (config.DD_PROFILING_DEBUG_SOURCE_MAPS) {
205
- const count = mapper.infoMap.size
206
- // eslint-disable-next-line eslint-rules/eslint-log-printf-style
207
- log.debug(() => {
208
- return count === 0
209
- ? 'Found no source maps'
210
- : `Found source maps for following files: [${[...mapper.infoMap.keys()].join(', ')}]`
211
- })
212
- }
213
- })
214
- .catch((error) => {
215
- log.error(error)
216
- })
181
+ // Initialization failures such as an unavailable native pprof binding are not expected to
182
+ // recover within the lifetime of this process. Preserve that decision without pretending the
183
+ // profiler is running or retrying setup on every subsequent config publication.
184
+ if (this.#startFailed) return false
185
+
186
+ // A prior stop()'s shutdown collection may still be encoding/exporting via #tags,
187
+ // #exporters and #endpointCounts. Wait for it to finish before this start() overwrites
188
+ // that shared state out from under it. Record the desired config rather than chaining
189
+ // straight onto #stopping, so a stop() arriving before it settles can cancel this restart.
190
+ if (this.#stopping) {
191
+ this.#pendingStart = config
192
+ return true
217
193
  }
218
194
 
219
195
  try {
196
+ const { tags: snapshotTags, exporters, flushInterval, profilers, uploadCompression, systemInfoReport } =
197
+ buildProfilingRuntime(config)
198
+ this.#config = config
199
+ this.#exporters = exporters
200
+ this.#flushInterval = flushInterval
201
+ this.#profilers = profilers
202
+ this.#currentSnapshotTags = snapshotTags
203
+ // A restart is installed only after the prior shutdown collection settles, so any endpoint
204
+ // counts left behind by a collection that produced no encodable profiles belong to the old run.
205
+ this.#endpointCounts.clear()
206
+ // Compression is initialized lazily and cached for a profiling run. A restarted profiler
207
+ // must derive it again from the newly built runtime instead of retaining the prior method
208
+ // or options.
209
+ this.#compressionFn = undefined
210
+ this.#compressionFnInitialized = false
211
+ this.#compressionOptions = undefined
212
+ this.#uploadCompression = uploadCompression
213
+ this.#systemInfoReport = systemInfoReport
214
+ if (this.#customLabelKeys.size > 0) {
215
+ this.#applyCustomLabelKeys()
216
+ }
217
+
218
+ this._setInterval()
219
+ // Log errors if the source map finder fails, but don't prevent the rest
220
+ // of the profiler from running without source maps.
221
+ let mapper
222
+ const { setLogger, SourceMapper } = require('@datadog/pprof')
223
+ setLogger(pprofLogger)
224
+
225
+ if (config.DD_PROFILING_SOURCE_MAP) {
226
+ mapper = new SourceMapper(config.DD_PROFILING_DEBUG_SOURCE_MAPS)
227
+ mapper.loadDirectory(process.cwd())
228
+ .then(() => {
229
+ if (config.DD_PROFILING_DEBUG_SOURCE_MAPS) {
230
+ const count = mapper.infoMap.size
231
+ // eslint-disable-next-line eslint-rules/eslint-log-printf-style
232
+ log.debug(() => {
233
+ return count === 0
234
+ ? 'Found no source maps'
235
+ : `Found source maps for following files: [${[...mapper.infoMap.keys()].join(', ')}]`
236
+ })
237
+ }
238
+ })
239
+ .catch((error) => {
240
+ log.error(error)
241
+ })
242
+ }
243
+
244
+ // Setup above does not start any sampler runtime resources. From this point onward, #stop()
245
+ // can safely clean up a partial start because #profilers and the rest of the runtime exist.
246
+ this.#enabled = true
220
247
  const start = new Date()
221
248
  const nearOOMCallback = this.#nearOOMExport.bind(this)
222
249
  for (const profiler of profilers) {
@@ -236,7 +263,17 @@ class Profiler extends EventEmitter {
236
263
  this._capture(this._timeoutInterval, start)
237
264
  } catch (error) {
238
265
  log.error(error)
239
- this.#stop()
266
+ this.#startFailed = true
267
+ if (this.enabled) {
268
+ try {
269
+ this.#stop()
270
+ } catch (stopError) {
271
+ // A cleanup failure must not leave the public running state stuck at true or escape into
272
+ // the customer application.
273
+ this.#enabled = false
274
+ log.error(stopError)
275
+ }
276
+ }
240
277
  return false
241
278
  }
242
279
 
@@ -258,11 +295,34 @@ class Profiler extends EventEmitter {
258
295
  }
259
296
 
260
297
  stop () {
298
+ // A stop() always reflects the latest desired state, so it cancels any restart queued by a
299
+ // start() that arrived while a prior shutdown collection was still in flight.
300
+ this.#pendingStart = undefined
301
+
261
302
  if (!this.enabled) return
262
303
 
263
304
  // collect and export current profiles
264
305
  // once collect returns, profilers can be safely stopped
265
- this._collect(snapshotKinds.ON_SHUTDOWN, false)
306
+ this.#stopping = this._collect(snapshotKinds.ON_SHUTDOWN, false)
307
+ .catch(error => {
308
+ // _collect() contains its own failures, but its cleanup can still throw. Nothing awaits
309
+ // this shutdown chain, so consume and log that failure instead of leaking a rejection.
310
+ log.error(error)
311
+ })
312
+ .finally(() => {
313
+ this.#stopping = undefined
314
+ if (this.#pendingStart) {
315
+ const config = this.#pendingStart
316
+ this.#pendingStart = undefined
317
+ // Unlike the synchronous entry point, nothing awaits this promise, so a throw here would
318
+ // become an unhandled rejection instead of a caught error.
319
+ try {
320
+ this.start(config)
321
+ } catch (error) {
322
+ log.error(error)
323
+ }
324
+ }
325
+ })
266
326
  this.#stop()
267
327
  }
268
328