dd-trace 6.16.0 → 6.17.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 (334) 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 +165 -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 +72 -12
  42. package/packages/datadog-instrumentations/src/cypress-config.js +0 -23
  43. package/packages/datadog-instrumentations/src/helpers/channel.js +0 -2
  44. package/packages/datadog-instrumentations/src/helpers/graphql-jit-runtime.js +0 -5
  45. package/packages/datadog-instrumentations/src/helpers/hooks.js +8 -0
  46. package/packages/datadog-instrumentations/src/helpers/instrumentation-utils.js +0 -3
  47. package/packages/datadog-instrumentations/src/helpers/pool-acquire.js +0 -6
  48. package/packages/datadog-instrumentations/src/helpers/register.js +4 -0
  49. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +72 -24
  50. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentation-registry.js +39 -0
  51. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +3 -17
  52. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +12 -0
  53. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/postgres.js +36 -0
  54. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/supabase.js +128 -0
  55. package/packages/datadog-instrumentations/src/helpers/rewriter/targets.json +16 -0
  56. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms/postgres.js +388 -0
  57. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +0 -5
  58. package/packages/datadog-instrumentations/src/helpers/router-helper.js +0 -1
  59. package/packages/datadog-instrumentations/src/jest.js +141 -51
  60. package/packages/datadog-instrumentations/src/knex.js +0 -1
  61. package/packages/datadog-instrumentations/src/mariadb-bundle.js +0 -24
  62. package/packages/datadog-instrumentations/src/mariadb.js +0 -2
  63. package/packages/datadog-instrumentations/src/mocha/common.js +0 -1
  64. package/packages/datadog-instrumentations/src/mocha/main.js +22 -25
  65. package/packages/datadog-instrumentations/src/mocha/utils.js +119 -49
  66. package/packages/datadog-instrumentations/src/mocha/webdriverio-protocol.js +0 -6
  67. package/packages/datadog-instrumentations/src/mocha/worker.js +14 -17
  68. package/packages/datadog-instrumentations/src/mysql2.js +0 -2
  69. package/packages/datadog-instrumentations/src/openai-realtime/audio-accumulator.js +241 -0
  70. package/packages/datadog-instrumentations/src/openai-realtime/events.js +76 -0
  71. package/packages/datadog-instrumentations/src/openai-realtime/index.js +301 -0
  72. package/packages/datadog-instrumentations/src/openai-realtime/session.js +998 -0
  73. package/packages/datadog-instrumentations/src/openai-realtime/turns.js +211 -0
  74. package/packages/datadog-instrumentations/src/openai.js +51 -12
  75. package/packages/datadog-instrumentations/src/oracledb.js +9 -3
  76. package/packages/datadog-instrumentations/src/playwright-reporter.js +3 -16
  77. package/packages/datadog-instrumentations/src/playwright.js +238 -55
  78. package/packages/datadog-instrumentations/src/postgres.js +7 -0
  79. package/packages/datadog-instrumentations/src/router.js +0 -2
  80. package/packages/datadog-instrumentations/src/rum-browser-scripts.js +0 -2
  81. package/packages/datadog-instrumentations/src/sequelize.js +0 -1
  82. package/packages/datadog-instrumentations/src/supabase.js +15 -0
  83. package/packages/datadog-instrumentations/src/vitest-main-no-worker-init.js +18 -18
  84. package/packages/datadog-instrumentations/src/vitest-main.js +37 -17
  85. package/packages/datadog-instrumentations/src/vitest-util.js +7 -1
  86. package/packages/datadog-instrumentations/src/vitest-worker.js +49 -13
  87. package/packages/datadog-instrumentations/src/webdriverio.js +23 -42
  88. package/packages/datadog-instrumentations/src/ws.js +0 -1
  89. package/packages/datadog-plugin-ai/src/utils.js +0 -2
  90. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/trace-checkpoint.js +0 -1
  91. package/packages/datadog-plugin-aws-durable-execution-sdk-js/src/util.js +0 -2
  92. package/packages/datadog-plugin-aws-sdk/src/base.js +0 -1
  93. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/utils.js +0 -1
  94. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +0 -1
  95. package/packages/datadog-plugin-aws-sdk/src/util.js +0 -1
  96. package/packages/datadog-plugin-azure-durable-functions/src/index.js +0 -1
  97. package/packages/datadog-plugin-cucumber/src/index.js +10 -0
  98. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +171 -75
  99. package/packages/datadog-plugin-cypress/src/finalization.js +0 -3
  100. package/packages/datadog-plugin-cypress/src/source-map-utils.js +0 -4
  101. package/packages/datadog-plugin-cypress/src/support.js +52 -7
  102. package/packages/datadog-plugin-graphql/src/resolve-error.js +1 -2
  103. package/packages/datadog-plugin-graphql/src/utils.js +0 -5
  104. package/packages/datadog-plugin-jest/src/index.js +13 -0
  105. package/packages/datadog-plugin-kafkajs/src/producer.js +0 -1
  106. package/packages/datadog-plugin-mocha/src/index.js +39 -11
  107. package/packages/datadog-plugin-mongodb-core/src/query.js +0 -1
  108. package/packages/datadog-plugin-openai/src/index.js +16 -1
  109. package/packages/datadog-plugin-openai/src/realtime.js +144 -0
  110. package/packages/datadog-plugin-openai-agents/src/integration.js +0 -4
  111. package/packages/datadog-plugin-openai-agents/src/util.js +0 -1
  112. package/packages/datadog-plugin-playwright/src/index.js +76 -9
  113. package/packages/datadog-plugin-postgres/src/index.js +167 -0
  114. package/packages/datadog-plugin-prisma/src/datadog-tracing-helper.js +0 -1
  115. package/packages/datadog-plugin-redis/src/index.js +15 -1
  116. package/packages/datadog-plugin-supabase/src/error.js +18 -0
  117. package/packages/datadog-plugin-supabase/src/index.js +21 -0
  118. package/packages/datadog-plugin-supabase/src/supabase-auth-js-gotrueclient-getuser.js +69 -0
  119. package/packages/datadog-plugin-supabase/src/supabase-functions-js-functionsclient-invoke.js +70 -0
  120. package/packages/datadog-plugin-supabase/src/supabase-postgrest-js-postgrestbuilder-then.js +122 -0
  121. package/packages/datadog-plugin-supabase/src/supabase-realtime-js-realtimechannel-send.js +66 -0
  122. package/packages/datadog-plugin-supabase/src/supabase-storage-js-handle-request.js +93 -0
  123. package/packages/datadog-plugin-supabase/src/url.js +17 -0
  124. package/packages/datadog-plugin-vitest/src/index.js +10 -0
  125. package/packages/datadog-plugin-ws/src/util.js +0 -4
  126. package/packages/datadog-turbopack/index.js +0 -6
  127. package/packages/datadog-turbopack/src/loader.js +0 -16
  128. package/packages/datadog-webpack/src/loader.js +0 -1
  129. package/packages/dd-trace/src/aiguard/client.js +2 -3
  130. package/packages/dd-trace/src/aiguard/evaluation.js +6 -12
  131. package/packages/dd-trace/src/aiguard/index.js +2 -2
  132. package/packages/dd-trace/src/aiguard/integrations/index.js +1 -1
  133. package/packages/dd-trace/src/aiguard/integrations/openai.js +81 -7
  134. package/packages/dd-trace/src/aiguard/messages/anthropic.js +0 -2
  135. package/packages/dd-trace/src/aiguard/messages/openai.js +64 -1
  136. package/packages/dd-trace/src/aiguard/messages/utils.js +0 -1
  137. package/packages/dd-trace/src/aiguard/redaction.js +0 -1
  138. package/packages/dd-trace/src/aiguard/sdk.js +1 -1
  139. package/packages/dd-trace/src/appsec/activation.js +1 -1
  140. package/packages/dd-trace/src/appsec/api_security/normalized-route.js +0 -5
  141. package/packages/dd-trace/src/appsec/api_security/sampler.js +0 -4
  142. package/packages/dd-trace/src/appsec/blocking/index.js +3 -3
  143. package/packages/dd-trace/src/appsec/downstream_requests.js +1 -4
  144. package/packages/dd-trace/src/appsec/iast/index.js +1 -1
  145. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +5 -5
  146. package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +1 -1
  147. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  148. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +3 -3
  149. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +8 -10
  150. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -2
  151. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +4 -1
  152. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +7 -7
  153. package/packages/dd-trace/src/appsec/index.js +2 -2
  154. package/packages/dd-trace/src/appsec/lambda.js +71 -2
  155. package/packages/dd-trace/src/appsec/rasp/utils.js +5 -1
  156. package/packages/dd-trace/src/appsec/remote_config.js +8 -6
  157. package/packages/dd-trace/src/appsec/reporter.js +10 -6
  158. package/packages/dd-trace/src/appsec/rule_manager.js +3 -3
  159. package/packages/dd-trace/src/appsec/sdk/track_event.js +0 -2
  160. package/packages/dd-trace/src/appsec/waf/index.js +2 -2
  161. package/packages/dd-trace/src/appsec/waf/waf_manager.js +8 -5
  162. package/packages/dd-trace/src/carrier.js +0 -5
  163. package/packages/dd-trace/src/ci-visibility/dynamic-atr-retries.js +104 -0
  164. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +0 -2
  165. package/packages/dd-trace/src/ci-visibility/efd-retry-policy.js +34 -3
  166. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +0 -1
  167. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +0 -1
  168. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +0 -1
  169. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/index.js +0 -4
  170. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/msgpack-to-json.js +0 -1
  171. package/packages/dd-trace/src/ci-visibility/exporters/ci-validation/sink.js +0 -2
  172. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +37 -15
  173. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +0 -3
  174. package/packages/dd-trace/src/ci-visibility/exporters/request.js +0 -11
  175. package/packages/dd-trace/src/ci-visibility/exporters/settings-cache-key.js +0 -1
  176. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +0 -1
  177. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +0 -6
  178. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -2
  179. package/packages/dd-trace/src/ci-visibility/requests/rate-limit.js +0 -1
  180. package/packages/dd-trace/src/ci-visibility/requests/upload-test-screenshot.js +0 -5
  181. package/packages/dd-trace/src/ci-visibility/requests/video-request.js +0 -1
  182. package/packages/dd-trace/src/ci-visibility/telemetry.js +13 -0
  183. package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +0 -1
  184. package/packages/dd-trace/src/ci-visibility/test-screenshot.js +0 -2
  185. package/packages/dd-trace/src/ci-visibility/test-video.js +0 -1
  186. package/packages/dd-trace/src/config/defaults.js +3 -2
  187. package/packages/dd-trace/src/config/generated-config-types.d.ts +73 -67
  188. package/packages/dd-trace/src/config/helper.js +0 -1
  189. package/packages/dd-trace/src/config/index.js +24 -24
  190. package/packages/dd-trace/src/config/parsers.js +34 -6
  191. package/packages/dd-trace/src/config/remote_config.js +25 -109
  192. package/packages/dd-trace/src/config/supported-configurations.json +139 -10
  193. package/packages/dd-trace/src/datastreams/encoding.js +0 -1
  194. package/packages/dd-trace/src/datastreams/pathway.js +0 -1
  195. package/packages/dd-trace/src/debugger/constants.js +10 -0
  196. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +62 -10
  197. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
  198. package/packages/dd-trace/src/debugger/devtools_client/guardrail-metrics.js +15 -0
  199. package/packages/dd-trace/src/debugger/devtools_client/index.js +103 -27
  200. package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +50 -7
  201. package/packages/dd-trace/src/debugger/devtools_client/log.js +3 -1
  202. package/packages/dd-trace/src/debugger/devtools_client/probe_sampler.js +21 -8
  203. package/packages/dd-trace/src/debugger/devtools_client/send.js +40 -14
  204. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +53 -13
  205. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +118 -71
  206. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +0 -3
  207. package/packages/dd-trace/src/debugger/devtools_client/status.js +20 -6
  208. package/packages/dd-trace/src/debugger/guardrail-metrics.js +167 -0
  209. package/packages/dd-trace/src/debugger/index.js +50 -2
  210. package/packages/dd-trace/src/debugger/inspect-segment.js +0 -3
  211. package/packages/dd-trace/src/debugger/probe_sampler.js +133 -9
  212. package/packages/dd-trace/src/debugger/probe_sampler_constants.js +31 -1
  213. package/packages/dd-trace/src/dogstatsd.js +0 -23
  214. package/packages/dd-trace/src/encode/0.4-cross-payload.js +0 -3
  215. package/packages/dd-trace/src/encode/0.4.js +0 -7
  216. package/packages/dd-trace/src/encode/0.5.js +0 -2
  217. package/packages/dd-trace/src/encode/tags-processors.js +0 -1
  218. package/packages/dd-trace/src/evp_proxy/discovery.js +0 -1
  219. package/packages/dd-trace/src/evp_proxy/path.js +0 -2
  220. package/packages/dd-trace/src/exporters/agent/writer.js +0 -1
  221. package/packages/dd-trace/src/exporters/agentless/index.js +0 -1
  222. package/packages/dd-trace/src/exporters/agentless/intake.js +0 -1
  223. package/packages/dd-trace/src/exporters/agentless/writer.js +0 -3
  224. package/packages/dd-trace/src/exporters/common/final-flush-request-tracker.js +0 -6
  225. package/packages/dd-trace/src/exporters/common/request.js +1 -0
  226. package/packages/dd-trace/src/exporters/common/url.js +0 -2
  227. package/packages/dd-trace/src/exporters/common/writer.js +0 -2
  228. package/packages/dd-trace/src/id.js +0 -11
  229. package/packages/dd-trace/src/llmobs/audio-codec.js +192 -0
  230. package/packages/dd-trace/src/llmobs/audio-utils.js +121 -0
  231. package/packages/dd-trace/src/llmobs/constants/audio.js +35 -0
  232. package/packages/dd-trace/src/llmobs/constants/prompts.js +14 -0
  233. package/packages/dd-trace/src/llmobs/constants/tags.js +17 -0
  234. package/packages/dd-trace/src/llmobs/eval-metric.js +0 -6
  235. package/packages/dd-trace/src/llmobs/experiments/dataset.js +0 -4
  236. package/packages/dd-trace/src/llmobs/experiments/experiment.js +0 -3
  237. package/packages/dd-trace/src/llmobs/experiments/index.js +7 -6
  238. package/packages/dd-trace/src/llmobs/experiments/util.js +1 -11
  239. package/packages/dd-trace/src/llmobs/index.js +1 -3
  240. package/packages/dd-trace/src/llmobs/noop.js +10 -0
  241. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +0 -4
  242. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +0 -1
  243. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +0 -4
  244. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +0 -2
  245. package/packages/dd-trace/src/llmobs/plugins/openai/constants.js +0 -2
  246. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +4 -6
  247. package/packages/dd-trace/src/llmobs/plugins/openai/realtime.js +285 -0
  248. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +16 -3
  249. package/packages/dd-trace/src/llmobs/prompts/cache.js +272 -0
  250. package/packages/dd-trace/src/llmobs/prompts/manager.js +639 -0
  251. package/packages/dd-trace/src/llmobs/prompts/noop.js +29 -0
  252. package/packages/dd-trace/src/llmobs/prompts/prompt.js +92 -0
  253. package/packages/dd-trace/src/llmobs/sdk.js +21 -6
  254. package/packages/dd-trace/src/llmobs/span_processor.js +81 -2
  255. package/packages/dd-trace/src/llmobs/tagger.js +30 -7
  256. package/packages/dd-trace/src/llmobs/telemetry.js +36 -4
  257. package/packages/dd-trace/src/llmobs/util.js +0 -34
  258. package/packages/dd-trace/src/llmobs/writers/base.js +0 -1
  259. package/packages/dd-trace/src/llmobs/writers/util.js +1 -2
  260. package/packages/dd-trace/src/log/channels.js +3 -0
  261. package/packages/dd-trace/src/log/index.js +23 -5
  262. package/packages/dd-trace/src/log-submission/log-submission-plugin.js +74 -6
  263. package/packages/dd-trace/src/msgpack/chunk.js +0 -1
  264. package/packages/dd-trace/src/openfeature/agentless_configuration_source.js +0 -12
  265. package/packages/dd-trace/src/openfeature/encoding.js +0 -2
  266. package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +0 -1
  267. package/packages/dd-trace/src/openfeature/index.js +0 -4
  268. package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +0 -1
  269. package/packages/dd-trace/src/openfeature/span-enrichment.js +0 -4
  270. package/packages/dd-trace/src/openfeature/writers/base.js +0 -6
  271. package/packages/dd-trace/src/openfeature/writers/exposures.js +0 -5
  272. package/packages/dd-trace/src/openfeature/writers/util.js +0 -4
  273. package/packages/dd-trace/src/opentelemetry/logs/logger.js +0 -1
  274. package/packages/dd-trace/src/opentelemetry/logs/logger_provider.js +0 -1
  275. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +0 -1
  276. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +0 -2
  277. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +0 -1
  278. package/packages/dd-trace/src/opentelemetry/metrics/otlp_span_stats_transformer.js +0 -1
  279. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +0 -1
  280. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -14
  281. package/packages/dd-trace/src/opentelemetry/metrics/time.js +0 -1
  282. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +30 -13
  283. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +0 -1
  284. package/packages/dd-trace/src/opentelemetry/span-helpers.js +0 -1
  285. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +0 -1
  286. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +0 -3
  287. package/packages/dd-trace/src/opentracing/propagation/text_map.js +0 -6
  288. package/packages/dd-trace/src/opentracing/span_context.js +0 -1
  289. package/packages/dd-trace/src/otel-thread-ctx.js +38 -11
  290. package/packages/dd-trace/src/payload-tagging/tagging.js +15 -3
  291. package/packages/dd-trace/src/plugins/ci_plugin.js +0 -1
  292. package/packages/dd-trace/src/plugins/database.js +2 -6
  293. package/packages/dd-trace/src/plugins/index.js +7 -0
  294. package/packages/dd-trace/src/plugins/plugin.js +0 -4
  295. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  296. package/packages/dd-trace/src/plugins/util/git.js +1 -3
  297. package/packages/dd-trace/src/plugins/util/http-otel-semantics.js +0 -1
  298. package/packages/dd-trace/src/plugins/util/llm.js +0 -2
  299. package/packages/dd-trace/src/plugins/util/status-validator.js +0 -1
  300. package/packages/dd-trace/src/plugins/util/test.js +21 -20
  301. package/packages/dd-trace/src/plugins/util/url.js +0 -5
  302. package/packages/dd-trace/src/priority_sampler.js +0 -6
  303. package/packages/dd-trace/src/process-tags/index.js +0 -1
  304. package/packages/dd-trace/src/profiler.js +132 -35
  305. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +0 -1
  306. package/packages/dd-trace/src/profiling/profiler.js +101 -41
  307. package/packages/dd-trace/src/profiling/ssi-heuristics.js +29 -15
  308. package/packages/dd-trace/src/propagation-hash/index.js +0 -1
  309. package/packages/dd-trace/src/proxy.js +21 -45
  310. package/packages/dd-trace/src/random_sampler.js +0 -4
  311. package/packages/dd-trace/src/rate_limiter.js +0 -4
  312. package/packages/dd-trace/src/remote_config/capabilities.js +1 -9
  313. package/packages/dd-trace/src/remote_config/index.js +0 -1
  314. package/packages/dd-trace/src/runtime_metrics/otlp_runtime_metrics.js +0 -3
  315. package/packages/dd-trace/src/sampler.js +0 -4
  316. package/packages/dd-trace/src/sampling_rule.js +0 -7
  317. package/packages/dd-trace/src/serverless/vercel.js +0 -1
  318. package/packages/dd-trace/src/serverless.js +0 -1
  319. package/packages/dd-trace/src/service-naming/index.js +0 -1
  320. package/packages/dd-trace/src/service-naming/schemas/util.js +0 -1
  321. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +7 -0
  322. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +5 -0
  323. package/packages/dd-trace/src/span_processor.js +2 -2
  324. package/packages/dd-trace/src/span_sampler.js +0 -1
  325. package/packages/dd-trace/src/standalone/product.js +2 -2
  326. package/packages/dd-trace/src/standalone/tracesource.js +0 -1
  327. package/packages/dd-trace/src/startup-log.js +1 -1
  328. package/packages/dd-trace/src/telemetry/endpoints.js +0 -8
  329. package/packages/dd-trace/src/telemetry/logs/index.js +16 -5
  330. package/packages/dd-trace/src/telemetry/logs/log-collector.js +16 -6
  331. package/packages/dd-trace/src/telemetry/metrics.js +0 -2
  332. package/packages/dd-trace/src/telemetry/telemetry.js +4 -1
  333. package/packages/dd-trace/src/util.js +13 -1
  334. package/vendor/dist/@datadog/openfeature-node-server/index.js +1 -1
@@ -1,8 +1,10 @@
1
1
  'use strict'
2
2
 
3
+ const { INCOMPLETE_REASON } = require('../../guardrail-metrics')
3
4
  const session = require('../session')
4
5
  const { collectObjectProperties } = require('./collector')
5
6
  const { processRawState, processRemoteObject } = require('./processor')
7
+ const { fieldCountSym } = require('./symbols')
6
8
 
7
9
  const BIGINT_MAX = (1n << 256n) - 1n
8
10
 
@@ -26,8 +28,13 @@ module.exports = {
26
28
  * @param {CaptureLimits} limits - The capture limits
27
29
  * @param {bigint} [deadlineNs] - The deadline in nanoseconds compared to `process.hrtime.bigint()`. Defaults to
28
30
  * {@link BIGINT_MAX}. If the deadline is reached, the snapshot will be truncated.
29
- * @returns {Promise<{ processLocalState: () => ReturnType<typeof processRawState>, fatalErrors: Error[] }>} The local
30
- * state for the call frame
31
+ * @returns {Promise<{
32
+ * processLocalState: () => ReturnType<typeof processRawState>,
33
+ * fatalErrors: Error[],
34
+ * incomplete: import('./processor').IncompleteCapture
35
+ * }>} The local state for the call frame. `incomplete` is only fully populated once `processLocalState` has run.
36
+ * Not every fatal error is recorded as a runtime error: the collector also raises one when it hits its large object
37
+ * safety threshold, which is reported as the field count limit it is.
31
38
  */
32
39
  async function getLocalStateForCallFrame (callFrame, limits, deadlineNs = BIGINT_MAX) {
33
40
  const { maxReferenceDepth, maxCollectionSize, maxFieldCount, maxLength } = limits
@@ -35,39 +42,63 @@ async function getLocalStateForCallFrame (callFrame, limits, deadlineNs = BIGINT
35
42
  const ctx = { deadlineReached: false, fatalErrors: [] }
36
43
  const opts = { maxReferenceDepth, maxCollectionSize, maxFieldCount, deadlineNs, ctx }
37
44
  const rawState = []
45
+ /** @type {import('./processor').IncompleteCapture} */
46
+ const incomplete = { reasons: 0 }
38
47
  /** @type {ReturnType<typeof processRawState> | null} */
39
48
  let processedState = null
40
49
 
41
- for (const scope of callFrame.scopeChain) {
42
- if (scope.type === 'global') continue // The global scope is too noisy
43
- const { objectId } = scope.object
44
- if (objectId === undefined) continue // I haven't seen this happen, but according to the types it's possible
50
+ const { scopeChain } = callFrame
51
+ for (const scope of scopeChain) {
52
+ if (!isCollectable(scope)) continue
53
+ const objectId = /** @type {string} */ (scope.object.objectId)
45
54
  try {
46
55
  // The objectId for a scope points to a pseudo-object whose properties are the actual variables in the scope.
47
56
  // This is why we can just call `collectObjectProperties` directly and expect it to return the in-scope variables
48
57
  // as an array.
49
58
  // eslint-disable-next-line no-await-in-loop
50
- rawState.push(...await collectObjectProperties(objectId, opts))
59
+ const variables = await collectObjectProperties(objectId, opts)
60
+ // A scope with more variables than the field count limit is trimmed like any other object, but since the scope
61
+ // itself is not part of the snapshot, the marker would be lost once its variables are spread into the state
62
+ if (variables[fieldCountSym] !== undefined) incomplete.reasons |= INCOMPLETE_REASON.FIELD_COUNT
63
+ rawState.push(...variables)
51
64
  } catch (err) {
65
+ incomplete.reasons |= INCOMPLETE_REASON.RUNTIME_ERROR
52
66
  ctx.fatalErrors.push(new Error(
53
67
  `Error getting local state for closure scope (type: ${scope.type}). ` +
54
68
  'Future snapshots for existing probes in this location will be skipped until the probes are re-applied',
55
69
  { cause: err } // TODO: The cause is not used by the backend
56
70
  ))
57
71
  }
58
- if (ctx.deadlineReached === true) break // TODO: Bad UX; Variables in remaining scopes are silently dropped
72
+ if (ctx.deadlineReached === true) {
73
+ // Nodes skipped within this scope carry the timeout marker and are recorded when processed (unless they end up
74
+ // redacted), but the remaining scopes are dropped without any marker.
75
+ // TODO: Bad UX; Variables in remaining scopes are silently dropped
76
+ // @ts-expect-error - findLast is available in Node.js 18+ but TypeScript doesn't know about it without ES2023 lib
77
+ if (scope !== scopeChain.findLast(isCollectable)) incomplete.reasons |= INCOMPLETE_REASON.TIMEOUT
78
+ break
79
+ }
59
80
  }
60
81
 
61
82
  // Delay calling `processRawState` so caller can resume the main thread before processing `rawState`
62
83
  return {
63
84
  processLocalState () {
64
- processedState ??= processRawState(rawState, maxLength)
85
+ processedState ??= processRawState(rawState, maxLength, incomplete)
65
86
  return processedState
66
87
  },
67
88
  fatalErrors: ctx.fatalErrors,
89
+ incomplete,
68
90
  }
69
91
  }
70
92
 
93
+ /**
94
+ * Returns whether the scope variables are collected into the snapshot.
95
+ * @param {import('inspector').Debugger.Scope} scope
96
+ */
97
+ function isCollectable (scope) {
98
+ // The global scope is too noisy, and a scope without an object id is possible according to the types
99
+ return scope.type !== 'global' && scope.object.objectId !== undefined
100
+ }
101
+
71
102
  /**
72
103
  * @typedef {object} CompiledCaptureExpression
73
104
  * @property {string} name - The name of the expression (used as key in snapshot)
@@ -82,6 +113,9 @@ async function getLocalStateForCallFrame (callFrame, limits, deadlineNs = BIGINT
82
113
  * @property {{ expr: string, message: string }[]} evaluationErrors - Transient errors from expression evaluation
83
114
  * (safe to retry)
84
115
  * @property {Error[]} fatalErrors - Fatal errors that should disable capture expressions for this probe permanently
116
+ * @property {import('./processor').IncompleteCapture} incomplete - The capture limits enforced on the expressions,
117
+ * including a runtime error for every expression that threw or could not be evaluated. Only fully populated once
118
+ * `processCaptureExpressions` has run.
85
119
  */
86
120
 
87
121
  /**
@@ -108,6 +142,8 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
108
142
  const evaluationErrors = []
109
143
  /** @type {Error[]} */
110
144
  const fatalErrors = []
145
+ /** @type {import('./processor').IncompleteCapture} */
146
+ const incomplete = { reasons: 0 }
111
147
  /** @type {Record<string, ReturnType<typeof processRemoteObject>> | null} */
112
148
  let processedResult = null
113
149
 
@@ -126,6 +162,7 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
126
162
 
127
163
  // Handle evaluation exceptions (maybe transient - bad expression, undefined var, etc.)
128
164
  if (exceptionDetails) {
165
+ incomplete.reasons |= INCOMPLETE_REASON.RUNTIME_ERROR
129
166
  evaluationErrors.push({ expr: name, message: extractErrorMessage(exceptionDetails) })
130
167
  continue
131
168
  }
@@ -156,9 +193,11 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
156
193
  }
157
194
 
158
195
  if (ctx.deadlineReached) {
159
- // Add the current expression (properties may be incomplete due to timeout)
196
+ // Add the current expression (properties may be incomplete due to timeout). Those carry the timeout marker
197
+ // and are recorded when processed, unless they end up redacted.
160
198
  rawResults.push({ name, remoteObject: result, maxLength })
161
- // Add stub entries for remaining uncaptured expressions
199
+ // Add stub entries for remaining uncaptured expressions. The stubs are used as-is, so record them here.
200
+ if (i + 1 < expressions.length) incomplete.reasons |= INCOMPLETE_REASON.TIMEOUT
162
201
  for (let j = i + 1; j < expressions.length; j++) {
163
202
  rawResults.push({
164
203
  name: expressions[j].name,
@@ -172,6 +211,7 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
172
211
 
173
212
  rawResults.push({ name, remoteObject: result, maxLength })
174
213
  } catch (err) {
214
+ incomplete.reasons |= INCOMPLETE_REASON.RUNTIME_ERROR
175
215
  fatalErrors.push(new Error(
176
216
  `Error capturing expression "${name}". ` +
177
217
  'Capture expressions for this probe will be skipped until the probe is re-applied',
@@ -189,7 +229,7 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
189
229
  for (const { name, remoteObject, maxLength } of rawResults) {
190
230
  // If the remote object has notCapturedReason (e.g., timeout), use it as-is without processing
191
231
  processedResult[name] = remoteObject.notCapturedReason === undefined
192
- ? processRemoteObject(remoteObject, maxLength)
232
+ ? processRemoteObject(remoteObject, maxLength, incomplete)
193
233
  : remoteObject
194
234
  }
195
235
 
@@ -197,6 +237,7 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
197
237
  },
198
238
  evaluationErrors,
199
239
  fatalErrors,
240
+ incomplete,
200
241
  }
201
242
  }
202
243
 
@@ -204,7 +245,6 @@ async function evaluateCaptureExpressions (callFrame, expressions, deadlineNs =
204
245
  * Extract the error message from the exception details.
205
246
  *
206
247
  * @param {import('inspector').Runtime.ExceptionDetails} exceptionDetails - The exception details
207
- * @returns {string} The error message
208
248
  */
209
249
  function extractErrorMessage (exceptionDetails) {
210
250
  const description = exceptionDetails.exception?.description
@@ -1,5 +1,6 @@
1
1
  'use strict'
2
2
 
3
+ const { INCOMPLETE_REASON } = require('../../guardrail-metrics')
3
4
  const { LARGE_OBJECT_SKIP_THRESHOLD } = require('./constants')
4
5
  const { collectionSizeSym, largeCollectionSkipThresholdSym, fieldCountSym, timeBudgetSym } = require('./symbols')
5
6
  const { normalizeName, REDACTED_IDENTIFIERS } = require('./redaction')
@@ -15,15 +16,24 @@ module.exports = {
15
16
  * @typedef {import('inspector').Runtime.RemoteObject & { properties?: object[] }} RemoteObjectWithProperties
16
17
  */
17
18
 
19
+ /**
20
+ * Accumulates which capture limits were enforced while processing a single event, so they can be reported once per
21
+ * event instead of once per affected node.
22
+ *
23
+ * @typedef {object} IncompleteCapture
24
+ * @property {number} reasons - Bitmask of {@link INCOMPLETE_REASON} flags
25
+ */
26
+
18
27
  /**
19
28
  * Process a RemoteObject into the snapshot format.
20
29
  *
21
30
  * @param {RemoteObjectWithProperties} remoteObject
22
31
  * @param {number} maxLength - Maximum string length
32
+ * @param {IncompleteCapture} incomplete - Receives the capture limits enforced on the object
23
33
  * @returns {object} The processed value in snapshot format
24
34
  */
25
- function processRemoteObject (remoteObject, maxLength) {
26
- return getPropertyValueRaw({ value: remoteObject }, maxLength)
35
+ function processRemoteObject (remoteObject, maxLength, incomplete) {
36
+ return getPropertyValueRaw({ value: remoteObject }, maxLength, incomplete)
27
37
  }
28
38
 
29
39
  // Matches classes in source code, no matter how it's written:
@@ -33,7 +43,15 @@ function processRemoteObject (remoteObject, maxLength) {
33
43
  // - Anonymous, with odd whitespace: class\n{}
34
44
  const CLASS_REGEX = /^class\s([^{]*)/
35
45
 
36
- function processProperties (props, maxLength) {
46
+ /**
47
+ * Process the collected properties of an object into the snapshot format.
48
+ *
49
+ * @param {object[]} props - The collected property descriptors
50
+ * @param {number} maxLength - Maximum string length
51
+ * @param {IncompleteCapture} incomplete - Receives the capture limits enforced on the properties
52
+ * @returns {Record<string, object>} The processed properties in snapshot format
53
+ */
54
+ function processProperties (props, maxLength, incomplete) {
37
55
  const result = {}
38
56
 
39
57
  for (const prop of props) {
@@ -42,20 +60,26 @@ function processProperties (props, maxLength) {
42
60
  if (name.includes('.')) {
43
61
  name = name.replaceAll('.', '_')
44
62
  }
45
- result[name] = getPropertyValue(prop, maxLength)
63
+ result[name] = getPropertyValue(prop, maxLength, incomplete)
46
64
  }
47
65
 
48
66
  return result
49
67
  }
50
68
 
69
+ // Capture limits enforced while processing a value that ends up redacted never make it into the snapshot, so they are
70
+ // not recorded as incomplete capture reasons either
71
+ const discardedIncomplete = { reasons: 0 }
72
+
51
73
  // TODO: Improve performance of redaction algorithm.
52
74
  // This algorithm is probably slower than if we embedded the redaction logic inside the functions below.
53
75
  // That way we didn't have to traverse objects that will just be redacted anyway.
54
- function getPropertyValue (prop, maxLength) {
55
- return redact(prop, getPropertyValueRaw(prop, maxLength))
76
+ function getPropertyValue (prop, maxLength, incomplete) {
77
+ return shouldRedactProperty(prop)
78
+ ? notCapturedRedacted(getPropertyValueRaw(prop, maxLength, discardedIncomplete).type)
79
+ : getPropertyValueRaw(prop, maxLength, incomplete)
56
80
  }
57
81
 
58
- function getPropertyValueRaw (prop, maxLength) {
82
+ function getPropertyValueRaw (prop, maxLength, incomplete) {
59
83
  // Special case for getters and setters which does not have a value property
60
84
  if (prop.get) {
61
85
  const hasGet = prop.get.type !== 'undefined'
@@ -69,15 +93,15 @@ function getPropertyValueRaw (prop, maxLength) {
69
93
 
70
94
  switch (prop.value?.type) {
71
95
  case 'object':
72
- return getObjectValue(prop.value, maxLength)
96
+ return getObjectValue(prop.value, maxLength, incomplete)
73
97
  case 'string':
74
- return toString(prop.value.value, maxLength)
98
+ return toString(prop.value.value, maxLength, incomplete)
75
99
  case 'number':
76
100
  return { type: 'number', value: prop.value.description } // use `description` to get it as string
77
101
  case 'boolean':
78
102
  return { type: 'boolean', value: prop.value.value === true ? 'true' : 'false' }
79
103
  case 'function':
80
- return toFunctionOrClass(prop.value, maxLength)
104
+ return toFunctionOrClass(prop.value, maxLength, incomplete)
81
105
  case undefined: // TODO: Add test for when a prop has no value. I think it's if it's defined after the breakpoint?
82
106
  case 'undefined':
83
107
  return { type: 'undefined' }
@@ -88,18 +112,19 @@ function getPropertyValueRaw (prop, maxLength) {
88
112
  default:
89
113
  // As of this writing, the Chrome DevTools Protocol doesn't allow any other types than the ones listed above, but
90
114
  // in the future new ones might be added.
115
+ incomplete.reasons |= INCOMPLETE_REASON.OTHER
91
116
  return { type: prop.value.type, notCapturedReason: 'Unsupported property type' }
92
117
  }
93
118
  }
94
119
 
95
- function getObjectValue (obj, maxLength) {
120
+ function getObjectValue (obj, maxLength, incomplete) {
96
121
  const timeBudgetReached = obj[timeBudgetSym] === true
97
122
 
98
123
  switch (obj.subtype) {
99
124
  case undefined:
100
- return toObject(obj.className, obj.properties, maxLength, timeBudgetReached)
125
+ return toObject(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
101
126
  case 'array':
102
- return toArray(obj.className, obj.properties, maxLength, timeBudgetReached)
127
+ return toArray(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
103
128
  case 'null':
104
129
  return { type: 'null', isNull: true }
105
130
  // case 'node': // TODO: What does this subtype represent?
@@ -113,28 +138,28 @@ function getObjectValue (obj, maxLength) {
113
138
  return { type: obj.className, value }
114
139
  }
115
140
  case 'map':
116
- return toMap(obj.className, obj.properties, maxLength, timeBudgetReached)
141
+ return toMap(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
117
142
  case 'set':
118
- return toSet(obj.className, obj.properties, maxLength, timeBudgetReached)
143
+ return toSet(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
119
144
  case 'error':
120
145
  // TODO: Convert stack trace to array to avoid string truncation or disable truncation in this case?
121
- return toObject(obj.className, obj.properties, maxLength, timeBudgetReached)
146
+ return toObject(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
122
147
  case 'proxy':
123
148
  // Use `description` instead of `className` as the `type` to get type of target object (`Proxy(Error)` vs `proxy`)
124
- return toObject(obj.description, obj.properties, maxLength, timeBudgetReached)
149
+ return toObject(obj.description, obj.properties, maxLength, timeBudgetReached, incomplete)
125
150
  case 'promise':
126
- return toObject(obj.className, obj.properties, maxLength, timeBudgetReached)
151
+ return toObject(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
127
152
  case 'typedarray':
128
- return toArray(obj.className, obj.properties, maxLength, timeBudgetReached)
153
+ return toArray(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
129
154
  case 'generator':
130
155
  // Use `subtype` instead of `className` to make it obvious it's a generator
131
- return toObject(obj.subtype, obj.properties, maxLength, timeBudgetReached)
156
+ return toObject(obj.subtype, obj.properties, maxLength, timeBudgetReached, incomplete)
132
157
  case 'arraybuffer':
133
- return toArrayBuffer(obj.className, obj.properties, maxLength, timeBudgetReached)
158
+ return toArrayBuffer(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
134
159
  case 'weakmap':
135
- return toMap(obj.className, obj.properties, maxLength, timeBudgetReached)
160
+ return toMap(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
136
161
  case 'weakset':
137
- return toSet(obj.className, obj.properties, maxLength, timeBudgetReached)
162
+ return toSet(obj.className, obj.properties, maxLength, timeBudgetReached, incomplete)
138
163
  // case 'iterator': // TODO: I've not been able to trigger this subtype
139
164
  // case 'dataview': // TODO: Looks like the internal ArrayBuffer is only accessible via the `buffer` getter
140
165
  // case 'webassemblymemory': // TODO: Looks like the internal ArrayBuffer is only accessible via the `buffer` getter
@@ -142,31 +167,34 @@ function getObjectValue (obj, maxLength) {
142
167
  default:
143
168
  // As of this writing, the Chrome DevTools Protocol doesn't allow any other subtypes than the ones listed above,
144
169
  // but in the future new ones might be added.
170
+ incomplete.reasons |= INCOMPLETE_REASON.OTHER
145
171
  return { type: obj.subtype, notCapturedReason: 'Unsupported object type' }
146
172
  }
147
173
  }
148
174
 
149
- function toFunctionOrClass (value, maxLength) {
175
+ function toFunctionOrClass (value, maxLength, incomplete) {
150
176
  const classMatch = value.description.match(CLASS_REGEX)
151
177
 
152
178
  if (classMatch === null) {
153
179
  // This is a function
154
180
  const timeBudgetReached = value[timeBudgetSym] === true
155
181
  // TODO: Would it make sense to detect if it's an arrow function or not?
156
- return toObject(value.className, value.properties, maxLength, timeBudgetReached)
182
+ return toObject(value.className, value.properties, maxLength, timeBudgetReached, incomplete)
157
183
  }
158
184
  // This is a class
159
185
  const className = classMatch[1].trim()
160
186
  return { type: className ? `class ${className}` : 'class' }
161
187
  }
162
188
 
163
- function toString (str, maxLength) {
189
+ function toString (str, maxLength, incomplete) {
164
190
  const size = str.length
165
191
 
166
192
  if (size <= maxLength) {
167
193
  return { type: 'string', value: str }
168
194
  }
169
195
 
196
+ incomplete.reasons |= INCOMPLETE_REASON.STRING_LENGTH
197
+
170
198
  return {
171
199
  type: 'string',
172
200
  value: str.slice(0, maxLength),
@@ -175,16 +203,17 @@ function toString (str, maxLength) {
175
203
  }
176
204
  }
177
205
 
178
- function toObject (type, props, maxLength, timeBudgetReached) {
179
- if (timeBudgetReached === true) return notCapturedTimeBudget(type)
180
- if (props === undefined) return notCapturedDepth(type)
206
+ function toObject (type, props, maxLength, timeBudgetReached, incomplete) {
207
+ if (timeBudgetReached === true) return notCapturedTimeBudget(type, incomplete)
208
+ if (props === undefined) return notCapturedDepth(type, incomplete)
181
209
 
182
210
  const result = {
183
211
  type,
184
- fields: processProperties(props, maxLength),
212
+ fields: processProperties(props, maxLength, incomplete),
185
213
  }
186
214
 
187
215
  if (props[fieldCountSym] !== undefined) {
216
+ incomplete.reasons |= INCOMPLETE_REASON.FIELD_COUNT
188
217
  result.notCapturedReason = 'fieldCount'
189
218
  result.size = props[fieldCountSym]
190
219
  }
@@ -192,27 +221,29 @@ function toObject (type, props, maxLength, timeBudgetReached) {
192
221
  return result
193
222
  }
194
223
 
195
- function toArray (type, elements, maxLength, timeBudgetReached) {
196
- if (timeBudgetReached === true) return notCapturedTimeBudget(type)
197
- if (elements === undefined) return notCapturedDepth(type)
224
+ function toArray (type, elements, maxLength, timeBudgetReached, incomplete) {
225
+ if (timeBudgetReached === true) return notCapturedTimeBudget(type, incomplete)
226
+ if (elements === undefined) return notCapturedDepth(type, incomplete)
198
227
 
199
228
  const result = {
200
229
  type,
201
230
  elements: elements.map((element) => {
202
- return getPropertyValue(element, maxLength)
231
+ return getPropertyValue(element, maxLength, incomplete)
203
232
  }),
204
233
  }
205
234
 
206
- setNotCaptureReasonOnCollection(result, elements)
207
- setNotCaptureReasonOnTooLargeCollection(result, elements)
235
+ setNotCaptureReasonOnCollection(result, elements, incomplete)
236
+ setNotCaptureReasonOnTooLargeCollection(result, elements, incomplete)
208
237
 
209
238
  return result
210
239
  }
211
240
 
212
- function toMap (type, pairs, maxLength, timeBudgetReached) {
213
- if (timeBudgetReached === true) return notCapturedTimeBudget(type)
214
- if (pairs === undefined) return notCapturedDepth(type)
215
- if (pairs.length > 0 && pairs.every(({ value }) => value[timeBudgetSym] === true)) return notCapturedTimeBudget(type)
241
+ function toMap (type, pairs, maxLength, timeBudgetReached, incomplete) {
242
+ if (timeBudgetReached === true) return notCapturedTimeBudget(type, incomplete)
243
+ if (pairs === undefined) return notCapturedDepth(type, incomplete)
244
+ if (pairs.length > 0 && pairs.every(({ value }) => value[timeBudgetSym] === true)) {
245
+ return notCapturedTimeBudget(type, incomplete)
246
+ }
216
247
 
217
248
  const result = {
218
249
  type,
@@ -227,32 +258,34 @@ function toMap (type, pairs, maxLength, timeBudgetReached) {
227
258
  // second containing the value of this entry of the Map.
228
259
 
229
260
  if (value[timeBudgetSym] === true) {
261
+ incomplete.reasons |= INCOMPLETE_REASON.TIMEOUT
230
262
  return [{ notCapturedReason: 'timeout' }, { notCapturedReason: 'timeout' }]
231
263
  }
232
264
  if (value.properties === undefined) {
265
+ incomplete.reasons |= INCOMPLETE_REASON.OTHER
233
266
  return [{ notCapturedReason: 'unknown' }, { notCapturedReason: 'unknown' }]
234
267
  }
235
268
 
236
269
  const shouldRedact = shouldRedactMapValue(value.properties[0])
237
- const key = getPropertyValue(value.properties[0], maxLength)
270
+ const key = getPropertyValue(value.properties[0], maxLength, incomplete)
238
271
  const val = shouldRedact
239
272
  ? notCapturedRedacted(value.properties[1].value.type)
240
- : getPropertyValue(value.properties[1], maxLength)
273
+ : getPropertyValue(value.properties[1], maxLength, incomplete)
241
274
  return [key, val]
242
275
  }),
243
276
  }
244
277
 
245
- setNotCaptureReasonOnCollection(result, pairs)
246
- setNotCaptureReasonOnTooLargeCollection(result, pairs)
278
+ setNotCaptureReasonOnCollection(result, pairs, incomplete)
279
+ setNotCaptureReasonOnTooLargeCollection(result, pairs, incomplete)
247
280
 
248
281
  return result
249
282
  }
250
283
 
251
- function toSet (type, values, maxLength, timeBudgetReached) {
252
- if (timeBudgetReached === true) return notCapturedTimeBudget(type)
253
- if (values === undefined) return notCapturedDepth(type)
284
+ function toSet (type, values, maxLength, timeBudgetReached, incomplete) {
285
+ if (timeBudgetReached === true) return notCapturedTimeBudget(type, incomplete)
286
+ if (values === undefined) return notCapturedDepth(type, incomplete)
254
287
  if (values.length > 0 && values.every(({ value }) => value[timeBudgetSym] === true)) {
255
- return notCapturedTimeBudget(type)
288
+ return notCapturedTimeBudget(type, incomplete)
256
289
  }
257
290
 
258
291
  const result = {
@@ -267,33 +300,42 @@ function toSet (type, values, maxLength, timeBudgetReached) {
267
300
  // children, of which there will always be exactly one, which contain the
268
301
  // actual value in this entry of the Set.
269
302
 
270
- if (value[timeBudgetSym] === true) return { notCapturedReason: 'timeout' }
271
- if (value.properties === undefined) return { notCapturedReason: 'unknown' }
303
+ if (value[timeBudgetSym] === true) {
304
+ incomplete.reasons |= INCOMPLETE_REASON.TIMEOUT
305
+ return { notCapturedReason: 'timeout' }
306
+ }
307
+ if (value.properties === undefined) {
308
+ incomplete.reasons |= INCOMPLETE_REASON.OTHER
309
+ return { notCapturedReason: 'unknown' }
310
+ }
272
311
 
273
- return getPropertyValue(value.properties[0], maxLength)
312
+ return getPropertyValue(value.properties[0], maxLength, incomplete)
274
313
  }),
275
314
  }
276
315
 
277
- setNotCaptureReasonOnCollection(result, values)
278
- setNotCaptureReasonOnTooLargeCollection(result, values)
316
+ setNotCaptureReasonOnCollection(result, values, incomplete)
317
+ setNotCaptureReasonOnTooLargeCollection(result, values, incomplete)
279
318
 
280
319
  return result
281
320
  }
282
321
 
283
- function toArrayBuffer (type, bytes, maxLength, timeBudgetReached) {
284
- if (timeBudgetReached === true) return notCapturedTimeBudget(type)
285
- if (bytes === undefined) return notCapturedDepth(type)
322
+ function toArrayBuffer (type, bytes, maxLength, timeBudgetReached, incomplete) {
323
+ if (timeBudgetReached === true) return notCapturedTimeBudget(type, incomplete)
324
+ if (bytes === undefined) return notCapturedDepth(type, incomplete)
286
325
 
287
326
  const size = bytes.length
288
327
 
289
- return size > maxLength
290
- ? {
291
- type,
292
- value: arrayBufferToString(bytes, maxLength),
293
- truncated: true,
294
- size: bytes.length,
295
- }
296
- : { type, value: arrayBufferToString(bytes, size) }
328
+ if (size > maxLength) {
329
+ incomplete.reasons |= INCOMPLETE_REASON.STRING_LENGTH
330
+ return {
331
+ type,
332
+ value: arrayBufferToString(bytes, maxLength),
333
+ truncated: true,
334
+ size: bytes.length,
335
+ }
336
+ }
337
+
338
+ return { type, value: arrayBufferToString(bytes, size) }
297
339
  }
298
340
 
299
341
  function arrayBufferToString (bytes, size) {
@@ -304,9 +346,8 @@ function arrayBufferToString (bytes, size) {
304
346
  return buf.toString()
305
347
  }
306
348
 
307
- function redact (prop, obj) {
308
- const name = getNormalizedNameFromProp(prop)
309
- return REDACTED_IDENTIFIERS.has(name) ? notCapturedRedacted(obj.type) : obj
349
+ function shouldRedactProperty (prop) {
350
+ return REDACTED_IDENTIFIERS.has(getNormalizedNameFromProp(prop))
310
351
  }
311
352
 
312
353
  function shouldRedactMapValue (key) {
@@ -323,15 +364,19 @@ function getNormalizedNameFromProp (prop) {
323
364
  return normalizeName(prop.name, prop.symbol !== undefined)
324
365
  }
325
366
 
326
- function setNotCaptureReasonOnCollection (result, collection) {
367
+ function setNotCaptureReasonOnCollection (result, collection, incomplete) {
327
368
  if (collection[collectionSizeSym] !== undefined) {
369
+ incomplete.reasons |= INCOMPLETE_REASON.COLLECTION_SIZE
328
370
  result.notCapturedReason = 'collectionSize'
329
371
  result.size = collection[collectionSizeSym]
330
372
  }
331
373
  }
332
374
 
333
- function setNotCaptureReasonOnTooLargeCollection (result, collection) {
375
+ function setNotCaptureReasonOnTooLargeCollection (result, collection, incomplete) {
334
376
  if (collection[largeCollectionSkipThresholdSym] !== undefined) {
377
+ // The collection was skipped entirely because it exceeded the skip threshold, which is a different limit than the
378
+ // `maxCollectionSize` limit that `collectionSize` represents
379
+ incomplete.reasons |= INCOMPLETE_REASON.OTHER
335
380
  result.notCapturedReason = `Large collection with too many elements (skip threshold: ${
336
381
  LARGE_OBJECT_SKIP_THRESHOLD
337
382
  })`
@@ -339,7 +384,8 @@ function setNotCaptureReasonOnTooLargeCollection (result, collection) {
339
384
  }
340
385
  }
341
386
 
342
- function notCapturedDepth (type) {
387
+ function notCapturedDepth (type, incomplete) {
388
+ incomplete.reasons |= INCOMPLETE_REASON.DEPTH
343
389
  return { type, notCapturedReason: 'depth' }
344
390
  }
345
391
 
@@ -347,6 +393,7 @@ function notCapturedRedacted (type) {
347
393
  return { type, notCapturedReason: 'redactedIdent' }
348
394
  }
349
395
 
350
- function notCapturedTimeBudget (type) {
396
+ function notCapturedTimeBudget (type, incomplete) {
397
+ incomplete.reasons |= INCOMPLETE_REASON.TIMEOUT
351
398
  return { type, notCapturedReason: 'timeout' }
352
399
  }
@@ -143,7 +143,6 @@ class PriorityQueue {
143
143
  *
144
144
  * @param {TreeNode} a - First node to compare
145
145
  * @param {TreeNode} b - Second node to compare
146
- * @returns {number} - > 0 if a has higher priority, < 0 if b has higher priority, 0 if equal
147
146
  */
148
147
  #compare (a, b) {
149
148
  const keyA = a.priorityKey
@@ -243,7 +242,6 @@ function parseJsonToTree (json) {
243
242
  *
244
243
  * @param {string} json - The JSON string to skip
245
244
  * @param {number} startIndex - The index to start skipping from
246
- * @returns {number} The index of the closing quote
247
245
  */
248
246
  function skipString (json, startIndex) {
249
247
  let index = startIndex + 1 // Skip opening quote
@@ -353,7 +351,6 @@ function selectNodesToPrune (root, bytesToRemove) {
353
351
  *
354
352
  * @param {string} json - The JSON string to rebuild
355
353
  * @param {Set<TreeNode>} prunedNodes - The set of nodes to replace with {"pruned":true}
356
- * @returns {string} The rebuilt JSON string
357
354
  */
358
355
  function rebuildJson (json, prunedNodes) {
359
356
  // Convert set to array and sort by start position (descending)