Skip to content

v5.105.0 proposal#8661

Closed
dd-octo-sts[bot] wants to merge 126 commits into
v5.xfrom
v5.105.0-proposal
Closed

v5.105.0 proposal#8661
dd-octo-sts[bot] wants to merge 126 commits into
v5.xfrom
v5.105.0-proposal

Conversation

@dd-octo-sts
Copy link
Copy Markdown
Contributor

@dd-octo-sts dd-octo-sts Bot commented May 27, 2026

  • [1382cfd4de] - (SEMVER-PATCH) ci(project): remove supported integrations push jobs (Juan Antonio Fernández de Alba) #8707
  • [947a5360d2] - (SEMVER-PATCH) chore(deps): bump axios from 1.15.2 to 1.16.0 in /integration-tests/webpack in the npm_and_yarn group across 1 directory (dependabot[bot]) #8705
  • [f1543762c4] - (SEMVER-MINOR) revert: feat(http,http2): apply http.endpoint and queryStringObfuscation to client spans (feat(http,http2): apply http.endpoint and queryStringObfuscation to client spans #8407) (Ruben Bridgewater) #8706
  • [68619de614] - (SEMVER-PATCH) perf(encode): consolidate the msgpack hot path (Ruben Bridgewater) #8504
  • [130446e69c] - (SEMVER-PATCH) perf(format): split addTag into typed helpers to kill throwaway {} al… (Ruben Bridgewater) #8513
  • [4c88a9753d] - (SEMVER-PATCH) fix(mongodb): unify obfuscateQuery sanitizer and speed up query tagging (Ruben Bridgewater) #8703
  • [cfb2f0113e] - (SEMVER-PATCH) chore(cypress): bump latest test version (Juan Antonio Fernández de Alba) #8701
  • [a8496bd01e] - (SEMVER-PATCH) fix(jest): report coverage metric without skipped suites (Juan Antonio Fernández de Alba) #8702
  • [c6be3b9c47] - (SEMVER-PATCH) fix(jest): gate coverage backfill by jest version (Juan Antonio Fernández de Alba) #8700
  • [c2810de6f3] - (SEMVER-MINOR) feat(cypress): report TIA line coverage totals in cypress (Juan Antonio Fernández de Alba) #8453
  • [42a4f4f24b] - (SEMVER-PATCH) ci: add retry with 60s delay to coverage, dd-sts-api-key, and node actions (Roch Devost) #8694
  • [7d1aa519a6] - (SEMVER-PATCH) docs(types): add missing properties into v5 ts file (Pablo Erhard) #8692
  • [4b2f5d2908] - (SEMVER-PATCH) fix(hono): set resource name for single-handler routes (William Conti) #8100
  • [42151577da] - (SEMVER-PATCH) chore(deps): update @apm-js-collab/code-transformer to 0.13.0 (Roch Devost) #8631
  • [328a44dd02] - (SEMVER-PATCH) ci(test-optimization): fix flaky cypress@latest before-hook timeout (Roch Devost) #8666
  • [8f1897b169] - (SEMVER-PATCH) fix(ci): rerun only failed jobs for cancelled workflows in all-green (Roch Devost) #8673
  • [3ed178ced1] - (SEMVER-PATCH) test(appsec): drain preload span before RASP SSRF axios tests (Roch Devost) #8652
  • [845d19d793] - (SEMVER-PATCH) ci: simplify pr-title workflow triggers and condition (Roch Devost) #8695
  • [9f9bcccd44] - (SEMVER-PATCH) fix(ci): cancel running workflows on all-green timeout, reduce retries and initial delay (Roch Devost) #8674
  • [5f75d2afae] - (SEMVER-PATCH) test(debugger): fix zombie processes causing flaky redact tests on Node.js 20 (Roch Devost) #8663
  • [90ac905be3] - (SEMVER-MINOR) feat(openfeature): add FFE span enrichment for APM traces (Sameeran Kunche) #8343
  • [0a7f3e0589] - (SEMVER-PATCH) chore(ci): fold codeowners-audit and verify-exercised-tests into npm run lint (Ruben Bridgewater) #8686
  • [0bae706bec] - (SEMVER-PATCH) fix(ts): add interface DatabaseInstrumentation into v5 ts file (Pablo Erhard) #8690
  • [e2b0fdcccf] - (SEMVER-PATCH) docs(llmobs): drop restated category rules from the LLMObs skills (Ruben Bridgewater) #8687
  • [11cb345d76] - (SEMVER-MINOR) feat(nats): experimental support for @nats-io/nats-core / @nats-io/transport-node (Thomas Hunter II) #8608
  • [68443e431c] - (SEMVER-PATCH) ci(profiling): capture Windows crash dumps via WER LocalDumps (Attila Szegedi) #8593
  • [c7e114cb1d] - (SEMVER-PATCH) fix(debugger): generalize @-prefix ref desugaring (Thomas Watson) #8628
  • [1c71ca14b7] - (SEMVER-PATCH) ci: install gpg before Codecov upload to fix intermittent failures (Roch Devost) #8487
  • [1d0301cd92] - (SEMVER-PATCH) fix(oracledb): keep caller SQL when tracing is suppressed (Ruben Bridgewater) #8685
  • [e50934bc8c] - (SEMVER-PATCH) ci(test-optimization): install Chrome in Docker image for Selenium tests (Roch Devost) #8669
  • [8cb2b7711f] - (SEMVER-PATCH) bench(encode): make the encoding bench reflect a real Node.js HTTP request (Ruben Bridgewater) #8668
  • [d3bea48de9] - (SEMVER-PATCH) ci(pr-title): allow bench as a Conventional Commits type (Ruben Bridgewater) #8683
  • [d885382d88] - (SEMVER-MINOR) feat(aiguard): evaluate openai SDK calls automatically (Alberto Vara) #8053
  • [5a08c20f35] - (SEMVER-MINOR) [test optimization] report ITR line coverage totals in cucumber (Juan Antonio Fernández de Alba) #8452
  • [19252d91e5] - (SEMVER-PATCH) chore(ci): Download authanywhere binary over https (Rithika Narayan) #8688
  • [707b21a534] - (SEMVER-MINOR) [test optimization] prevent payload loss (Sebastián Kay) #8658
  • [a611dc5a06] - (SEMVER-MINOR) [test optimization] report ITR line coverage totals in mocha (Juan Antonio Fernández de Alba) #8450
  • [485a6474a3] - (SEMVER-MINOR) [test optimization] report TIA line coverage totals in jest (Juan Antonio Fernández de Alba) #8541
  • [aba729a656] - (SEMVER-PATCH) fix(ci): install Playwright browser dependencies (Juan Antonio Fernández de Alba) #8671
  • [664d873abb] - (SEMVER-PATCH) ci: pin all Windows runners to windows-2022 (Roch Devost) #8675
  • [e6dc6753de] - (SEMVER-PATCH) perf(pino): inject dd into the JSON line, skip the Proxy view (Ruben Bridgewater) #8501
  • [f99bb7a8f7] - (SEMVER-PATCH) fix(llmobs): cover every LLMObs span registration with OTel bridge tags (MLOS-591) (Zachary Groves)
  • [78ecd98e06] - (SEMVER-PATCH) perf(plugins/util/web): trim request-lifecycle helper work (Ruben Bridgewater) #8492
  • [f0e4773115] - (SEMVER-MINOR) feat(tracing): stamp manual spans through span.finish() resolution (Pablo Erhard) #8621
  • [55ed50f87e] - (SEMVER-MINOR) feat(http,http2): apply http.endpoint and queryStringObfuscation to client spans (Ruben Bridgewater) #8407
  • [696841f8cc] - (SEMVER-PATCH) perf(graphql): tighten resolver execute hot path (Ruben Bridgewater) #8498
  • [5c43988b36] - (SEMVER-PATCH) chore: update protobufjs, ttlcache, and code-transformer (Ruben Bridgewater) #8656
  • [75b7743aa2] - (SEMVER-PATCH) perf(span): write tags directly on _tags in setTag and addTags (Ruben Bridgewater) #8507
  • [f9016be6a8] - (SEMVER-PATCH) perf(fastify): fast-path addHook wrapper when no parser channels have… (Ruben Bridgewater) #8516
  • [33a821da2b] - (SEMVER-PATCH) chore(release): replace semver-major exclusion with only-land-on-next label (Roch Devost) #8660
  • [a8a566d308] - (SEMVER-PATCH) test(profiling): stabilize Poisson sampling filter spec (Attila Szegedi) #8659
  • [5344d3f2cd] - (SEMVER-MINOR) feat: add Node.js 26 support (Ruben Bridgewater) #8429
  • [2516fe8981] - (SEMVER-PATCH) ci(playwright): install libatomic for Node 26 (Juan Antonio Fernández de Alba) #8657
  • [d87533afc0] - (SEMVER-PATCH) fix(ci): add unzip to Playwright Docker image (Roch Devost) #8615
  • [a1fa4434ec] - (SEMVER-PATCH) fix(dbm): rename _dd.dbm.propagation_hash to _dd.propagated_hash (Thomas Hunter II) #8643
  • [2c1d5ae3cc] - (SEMVER-PATCH) fix(plugins): scope extractIp per-plugin instead of module-level (Ruben Bridgewater) #8508
  • [fe7d7a35f2] - (SEMVER-PATCH) chore(deps-dev): bump eslint-plugin-jsdoc from 62.9.0 to 63.0.0 (dependabot[bot]) #8648
  • [94c23b4bee] - (SEMVER-PATCH) chore(deps): bump the gh-actions-packages group across 3 directories with 3 updates (dependabot[bot]) #8649
  • [b210ba395b] - (SEMVER-PATCH) chore(deps): bump oxc-parser from 0.130.0 to 0.132.0 in the runtime-minor-and-patch-dependencies group across 1 directory (dependabot[bot]) #8647
  • [3e7de49119] - (SEMVER-PATCH) chore(deps-dev): bump the dev-minor-and-patch-dependencies group across 1 directory with 3 updates (dependabot[bot]) #8646
  • [db4a61149f] - (SEMVER-PATCH) chore(deps): bump the serverless group across 1 directory with 13 updates (dependabot[bot]) #8645
  • [e6e0689155] - (SEMVER-MINOR) feat(dbm): add dynamic_service propagation mode (Andrea Marziali) #8592
  • [b7bbc4b6b3] - (SEMVER-PATCH) add workflow to validate pull request title and sync labels (Roch Devost) #8196
  • [c2470f1f26] - (SEMVER-PATCH) ci(node): replace version cache with pinned versions from test/plugins/versions (Roch Devost) #8617
  • [49f16f10fc] - (SEMVER-PATCH) test(http2): fix flaky cancelled-request span assertion (Roch Devost) #8642
  • [fb120f1b97] - (SEMVER-PATCH) test(http2): avoid port reuse in server tests (Roch Devost) #8641
  • [3e0eceb16c] - (SEMVER-PATCH) perf(profiler): skip redundant setContext under AsyncContextFrame (Attila Szegedi) #8638
  • [5a0644eb21] - (SEMVER-PATCH) perf(span): fast-path setTag for the common non-sampling case (Pablo Erhard) #8640
  • [cd7fee8ce2] - (SEMVER-MINOR) feat(dns): instrument dns.promises API (Ruben Bridgewater) #8404
  • [dd068f1764] - (SEMVER-MINOR) feat(kafkajs): instrument producer.sendBatch (Ruben Bridgewater) #8403
  • [8a377d11eb] - (SEMVER-PATCH) perf(mongodb): fast path sanitiseAndStringify for flat-primitive filters (Ruben Bridgewater) #8514
  • [6e3846019c] - (SEMVER-PATCH) perf(router): consolidate per-request state, drop redundant ALS read (Ruben Bridgewater) #8509
  • [59951d598c] - (SEMVER-PATCH) perf(propagation): cheap extract on carriers without propagation context (Ruben Bridgewater) #8511
  • [c943187407] - (SEMVER-PATCH) perf(shimmer): reuse name and length descriptor literals (Ruben Bridgewater) #8515
  • [3e9c9fb635] - (SEMVER-MINOR) feat(opentracing): tag accessor API on span context + lint rule (Bryan English) #8491
  • [cd376c2cf3] - (SEMVER-MINOR) feat(oracledb): inject DBM SQL comment (Bowen Brooks) #8481
  • [a7318b6201] - (SEMVER-PATCH) chore(deps): bump @datadog/datadog-ci from 5.16.0 to 5.17.0 in /.github/actions/datadog-ci in the runtime-minor-and-patch-dependencies group across 1 directory (dependabot[bot]) #8570
  • [9641153901] - (SEMVER-MINOR) test-optimization(feat): Add cypress command spans (analog to playwright steps) (Sebastián Kay) #8580
  • [491710ef63] - (SEMVER-PATCH) chore(deps): bump the test-optimization group across 1 directory with 8 updates (dependabot[bot]) #8623
  • [2d3ff214fc] - (SEMVER-PATCH) chore(ci) update one-pipeline (gh-worker-campaigns-3e9aa4[bot]) #8636
  • [9130e0e0c6] - (SEMVER-PATCH) fix(aws-sdk): hook @smithy/core/client.Client.send for >=3.1046 clients (Ruben Bridgewater) #8532
  • [a6e6d25603] - (SEMVER-PATCH) fix(graphql): fix field-type tag, release contexts WeakMap, and more (Ruben Bridgewater) #8502
  • [9c7cde1371] - (SEMVER-PATCH) chore(test): bump mongodb to 7.2.0 and mongoose to 9.6.2 (Ruben Bridgewater) #8533
  • [0518beee67] - (SEMVER-PATCH) perf(plugin): drop per-publish storage lookup and handler rest-spread (Ruben Bridgewater) #8512
  • [b032ef455d] - (SEMVER-PATCH) chore(deps): bump the ai-and-llm group across 1 directory with 4 updates (dependabot[bot]) #8632
  • [659ad0005a] - (SEMVER-PATCH) [test optimization] support playwright 1.60 with rewriter hooks (Juan Antonio Fernández de Alba) #8590
  • [e0b94eca0c] - (SEMVER-PATCH) fix(eslint): skip autofix on ${} in string literal (Thomas Watson) #8627
  • [eb74c995a9] - (SEMVER-PATCH) chore(deps): bump the ai-and-llm group across 1 directory with 10 updates (dependabot[bot]) #8624
  • [8b9481fca9] - (SEMVER-PATCH) chore: deactivate eslint-require-boolean-assert-message (Ruben Bridgewater) #8620
  • [5763151c0e] - (SEMVER-PATCH) test(test-optimization): replace nock with direct stub in git_metadata tests (Roch Devost) #8613
  • [b50f1cad1d] - (SEMVER-PATCH) chore(deps): bump the test-versions group across 1 directory with 2 updates (dependabot[bot]) #8622
  • [4b3a0f05c4] - (SEMVER-PATCH) chore(log): drop the orphaned StructuredLogPlugin subclass (Ruben Bridgewater) #8579
  • [59ea620f0d] - (SEMVER-PATCH) fix(ci): always write flakiness report and fire Slack notification (Roch Devost) #8609
  • [2be6d4286e] - (SEMVER-PATCH) chore(deps): bump qs from 6.15.0 to 6.15.2 (dependabot[bot]) #8612
  • [b92c5df537] - (SEMVER-PATCH) ci(coverage): patch istanbul-lib-coverage's getLineCoverage in postinstall (Ruben Bridgewater) #8576
  • [f031818d89] - (SEMVER-PATCH) chore(ci): update dd-sts-action to v1.0.3 (Roch Devost) #8603
  • [761d5a70ba] - (SEMVER-PATCH) chore(deps): bump qs from 6.15.1 to 6.15.2 in /benchmark/sirun/startup/everything-fixture in the npm_and_yarn group across 1 directory (dependabot[bot]) #8611
  • [8e57bd7d41] - (SEMVER-PATCH) fix(ci): replace setup-bun with npm install to avoid GitHub rate limits (Roch Devost) #8616
  • [de48a2db85] - (SEMVER-PATCH) fix(ci): fix azure-functions cosmosdb test regressions (Roch Devost) #8610
  • [2a1b0e4e2a] - (SEMVER-PATCH) add openai error type (Sam Brenner) #8605
  • [e7f8e7a928] - (SEMVER-PATCH) fix(ci): restore azure-cosmos lint and fix electron packaging on Node 24.16+ (Roch Devost) #8604
  • [126cb67d0d] - (SEMVER-MINOR) feat(azure/cosmos): add Azure CosmosDB integration (Rithika Narayan) #7943
  • [ae4481fabb] - (SEMVER-PATCH) test(profiling): bump OOM extension size to 20MB for Node 22+ headroom (Attila Szegedi) #8564
  • [9767d0f752] - (SEMVER-PATCH) ci(test-optimization): build versioned Playwright Docker image in GHCR (Roch Devost) #8594
  • [45462e3600] - (SEMVER-PATCH) chore(deps-dev): bump the dev-minor-and-patch-dependencies group across 1 directory with 4 updates (dependabot[bot]) #8561
  • [eed98dab7b] - (SEMVER-PATCH) chore(deps): bump uuid from 9.0.1 to 14.0.0 in /benchmark/sirun/startup/everything-fixture in the npm_and_yarn group across 1 directory (dependabot[bot]) #8596
  • [53292acb4c] - (SEMVER-PATCH) chore(deps): bump the ai-and-llm group across 1 directory with 8 updates (dependabot[bot]) #8601
  • [9013e58945] - (SEMVER-PATCH) ci: work around actions/cache windows flakiness (Roch Devost) #8584
  • [526a2183c1] - (SEMVER-PATCH) fix(electron): increase assertSomeTraces timeout for IPC window tests (Roch Devost) #8597
  • [c94e32e027] - (SEMVER-PATCH) ci: only run SSI tests on master, release proposals, and labeled PRs (Roch Devost) #8485
  • [c0a31e9bcc] - (SEMVER-PATCH) ci: structured retry and longer network-timeout for CI installs (Ruben Bridgewater) #8566
  • [e385b8a047] - (SEMVER-PATCH) ci(verify-tests): flag specs no CI invocation reaches (Ruben Bridgewater) #8543
  • [625f561c5d] - (SEMVER-PATCH) perf(http-server): reuse request ctx and cache config in plugin start (Ruben Bridgewater) #8506
  • [105fdbaef1] - (SEMVER-PATCH) bump datadog/pprof (Ilyas Shabi) #8565
  • [098e20fbf8] - (SEMVER-PATCH) bump native-iast-taint-tracking (Ilyas Shabi) #8591
  • [bcf2f1dc74] - (SEMVER-PATCH) [test optimization] normalize seed suffix in test names in jest (Juan Antonio Fernández de Alba) #8587
  • [600610bcaa] - (SEMVER-PATCH) chore(eslint): require messages on boolean test assertions (Thomas Watson) #8537
  • [3929ed654d] - (SEMVER-PATCH) fix(electron): guard find() result and increase startApp timeout (Roch Devost) #8559
  • [ce294bf9c0] - (SEMVER-PATCH) ci: fix node version cache path on Windows (Roch Devost) #8578
  • [7caa2c988a] - (SEMVER-PATCH) fix(test): retry topic creation on UNKNOWN_TOPIC_OR_PARTITION in kafkajs tests (William Conti) #8469
  • [ad4b5e7cc7] - (SEMVER-PATCH) ci: avoid Yarn quarantine for Datadog packages (Ilyas Shabi) #8577
  • [f8a60480e3] - (SEMVER-PATCH) chore: update dependabot and support ranges (Ruben Bridgewater) #8337
  • [d72f7da8c0] - (SEMVER-PATCH) chore(deps): bump the runtime-minor-and-patch-dependencies group across 1 directory with 2 updates (dependabot[bot]) #8562

BridgeAR and others added 30 commits May 27, 2026 15:35
…d off in v6 (#8319)

* refactor(span)!: gate addLink(spanContext, attributes) legacy overload off in v6

v5 keeps the OpenTracing-style positional shape; v6 only accepts `addLink({ context, attributes })` on both the OpenTracing `Span` and the OpenTelemetry bridge. Tests that exercised the legacy form switch to the canonical shape (works on both versions) or are gated with `DD_MAJOR < 6`.

* fix: convert remaining addLink call sites to canonical form

`addLink(spanContext, attrs)` no longer works on v6 — the legacy
positional overload now TypeErrors on `context._ddContext`. Several
plugins (`kafkajs`, `google-cloud-pubsub`, `azure-*`), the OTel
`addSpanPointer` helper, and the `dd-trace-api` plugin spec still
passed that shape. They switch to `addLink({ context, attributes })`,
which also works on v5. `docs/test.ts` drops the two legacy-form
lines that no longer compile against the updated type definitions, and
the `version` import in `opentracing/span.js` moves above
`./span_context` to satisfy `import/order`. A `DD_MAJOR < 6`-gated
regression test on the OpenTracing `Span` pins the legacy v5 path so
v5 coverage stays after the canonical-only conversion in the
surrounding tests.
…ss 1 directory with 2 updates (#8562)

Bumps the runtime-minor-and-patch-dependencies group with 2 updates in the / directory: [@datadog/openfeature-node-server](https://github.com/DataDog/openfeature-js-client/tree/HEAD/packages/node-server) and [oxc-parser](https://github.com/oxc-project/oxc/tree/HEAD/napi/parser).


Updates `@datadog/openfeature-node-server` from 1.1.2 to 1.2.1
- [Release notes](https://github.com/DataDog/openfeature-js-client/releases)
- [Changelog](https://github.com/DataDog/openfeature-js-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DataDog/openfeature-js-client/commits/v1.2.1/packages/node-server)

Updates `oxc-parser` from 0.129.0 to 0.130.0
- [Release notes](https://github.com/oxc-project/oxc/releases)
- [Changelog](https://github.com/oxc-project/oxc/blob/main/napi/parser/CHANGELOG.md)
- [Commits](https://github.com/oxc-project/oxc/commits/crates_v0.130.0/napi/parser)

---
updated-dependencies:
- dependency-name: "@datadog/openfeature-node-server"
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: runtime-minor-and-patch-dependencies
- dependency-name: oxc-parser
  dependency-version: 0.130.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: runtime-minor-and-patch-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore: update dependabot and support ranges

Split dependabot into multiple groups so one laggy module no longer
blocks the others, refresh the test fixtures to match, and regenerate
the supported-versions output. Aerospike's `['4', '5', '6']` ->
`['>=4']` and stripe's explicit list -> `['>=9 <22']` are kept --
aerospike v7 has not shipped on npm and stripe's range collapse
covers the same set.

Multer's `^1.4.4-lts.1` -> `>=1.4.4-lts.1` widening moves to a
separate PR per @watson's review (would have added v2 support to a
"support ranges" refresh).

Refs: #8337 (comment)

* chore(deps): raise plugin-versions Dependabot PR cap to fit cohort design

The cohort grouping under `/packages/dd-trace/test/plugins/versions` only
helps when the matching PRs can open in parallel. With
`open-pull-requests-limit: 1` Dependabot still serializes the cohorts, so
a blocked group continues to stall every other group — the bottleneck the
groups were meant to remove. Bump to 10 (one slot per cohort plus
headroom).

Refs: #8337

* fix(test): scope same-name externals install by PACKAGE_VERSION_RANGE

Externals entries whose `name` matches the plugin key (e.g. the new
aerospike entry that mirrors the addHook versions for `withVersions`)
ignored `PACKAGE_VERSION_RANGE` and forced every major to install on
every CI job. Aerospike@4 has no Node-22 prebuilt binary, aerospike@6
has no Node-16 binary -- the per-major aerospike matrix can't boot
once the externals entry exists.

Also move aerospike's `hoistingLimits` install-config out of the
`!external` branch so the externals-loop write does not silently
overwrite the workspace setup the internal pass put down.

* fixup!
ci: avoid Yarn quarantine for Datadog packages
On Windows, the JS-based actions/cache action and Git Bash resolve /tmp
to different directories, causing the cached Node.js version file to
never be found. This means check-latest always fires on Windows, making
a manifest API call that can fail. Replace /tmp with ${{ runner.temp }}
/ $RUNNER_TEMP which resolves consistently across both contexts.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* chore(eslint): require messages on boolean test assertions

Add a custom ESLint rule that flags `assert(...)` / `assert.ok(...)`
calls whose first argument is a non-trivial expression and no second
message argument is provided. Without a message, failures only report
"Expected true, got false", hiding the actual value being asserted on —
debugging a flaky `assert.ok(duration >= 1000)` is painful when you
can't tell if `duration` was 500ms or 5ms.

Self-describing shapes are still allowed without a message: bare
references (`isReady`, `obj.prop`), structural unary ops (`!x`,
`typeof x`, `delete obj.k`), `in` / `instanceof` with trivial operands,
predicate-style calls (`arr.includes('foo')`, `Array.isArray(x)`), and
zero-arg method-chain calls used as getter-style navigation
(`span.context()._tags`).

Scoped to test files via the existing `TEST_FILES` glob.

* Add auto-fix

* Apply auto-fixes

* AI fix
* bump datadog/pprof

* add node-gyp-build resolutions

* update pprof nodejs version
…#8506)

The Express autocannon profile pins the HTTP server entry as the
dominant per-request hot path. Each request allocated three
short-lived `{ req, res, abortController }` / `{ req }` objects
through the instrumentation -> plugin -> AppSec chain, the plugin
re-ran `serviceName()`, `operationName()`, and a
`{ ...this.config, service }` spread on every call, and a couple of
secondary frames did per-call work that was easy to drop.

Three coordinated pieces tighten the path:

1. `wrapEmit` keeps one `{ req, res, abortController }` ctx alive and
   shares it with `exitServerCh` and the plugin's forward to
   `incomingHttpRequestStart`. This resolves the explicit
   `TODO: no need to make a new object here` on the AppSec publish;
   the start, exit, and AppSec subscribers all read from the same
   message without mutating it.
2. `HttpServerPlugin#configure` resolves `serviceName`, `operationName`,
   `serviceSource`, and the pre-merged `{ ...this.config, service }`
   once into the new `#startConfig`, `#operationName`, and
   `#serviceSource` private fields. The hot path reads cached fields;
   the next `configure` call refreshes them so remote-config flips
   still win.
3. `wrapResponseEmit` checks the event name with `||` instead of
   allocating a `['finish', 'close']` array on every response emit,
   and `wrapWriteHead` skips a no-op `Object.assign(this.getHeaders(),
   undefined)` when `writeHead` is called without an explicit headers
   object (the common Express case).

The per-request allocations the diff removes are deterministic from
reading the code; the targeted profile frames stop paying lookup
cost they did before. Span shape (resource, http.method, http.url,
http.status_code, http.route), CORS / correlation header handling,
and the `incomingHttpRequestStart` published message all match the
prior diagnostic-channel payload by deep-equal.
* ci(verify-tests): flag specs no CI invocation reaches

The existing "spec is matched by some script glob" check passes whenever
a `package.json` test script could in principle run a spec. It misses
the inverse failure: a glob exists but no workflow ever sets the env
(typically `PLUGINS=<name>`) that would expand the glob to reach the
spec. That is how PR #8516's
`packages/datadog-instrumentations/test/fastify.spec.js` slipped through
with no CI invocation running it, and why codecov reported 8 new lines
as patch misses despite the spec covering them locally.

Two prerequisites ride along so the joint check produces truthful
results:

1. `normalizeScriptGlob` collapsed every `@(${PLUGINS})` to `*` even in
   `preserveEnv` mode, so a single-plugin job (e.g. `PLUGINS=bluebird`)
   looked like it exercised every spec in the same directory. Unwrap
   the extglob to `${PLUGINS}` before the env-aware expansion runs.

2. `instrumentation-http` wraps `yarn test:instrumentations:ci` in
   `nick-fields/retry@*`'s `command:` input. Treat that input like an
   inline `run:` so the verifier sees the underlying invocation.

On `master` the new check surfaces 14 pre-existing orphans
(instrumentation specs with no matching `PLUGINS=` job, plus two plugin
integration-test specs and `datadog-plugin-jest/test/util.spec.js`);
closing each is out of scope and tracked in follow-up PRs.

* ci(instrumentation): run 11 orphan instrumentation specs

`packages/datadog-instrumentations/test/{ai,aws-sdk,couchbase,crypto,
express-multi-version,fetch,hono,http-client-options,otel-sdk-trace,
stripe,zlib}.spec.js` are matched by `test:instrumentations`' glob but
no workflow set `PLUGINS=<name>` for `test:instrumentations:ci`, so the
new joint-coverage check in `scripts/verify-exercised-tests.js` flagged
each as never reached by a CI invocation. Add the matching
`instrumentation-<name>` jobs alongside the existing siblings; nine of
the eleven are plain Node unit specs (proxyquire / agent harness) and
need no service containers, so the existing `instrumentations/test`
composite action runs them as-is.

Two specs need a custom job shape on top of that:

1. `couchbase` ships its own libcouchbase whose 3.x line only builds on
   Node 18 and whose 4.2+ line only builds on Node 20+; the composite
   action runs both oldest (18) and latest (24), so neither range
   survives the install on its own. Use a matrix that pins one Node
   version per range, mirroring the existing `couchbase` plugin job.

2. `http-client-options` listened on `127.0.0.1` only, but
   `http.request(undefined, callback)` resolves to `localhost`, which
   Node 18+ may resolve to `::1` first -- the request then fails with
   `ECONNREFUSED ::1:<port>` before the spec can assert. Bind the test
   server to all interfaces.

* ci(apm-integrations): run axios/body-parser integration-test specs

`packages/datadog-plugin-{axios,body-parser}/test/integration-test/client.spec.js`
are matched by `test:integration:plugins`' glob but no workflow set
`PLUGINS=<name>` for `test:integration:plugins:coverage`; the existing
`axios:` and `body-parser:` jobs only invoked `plugins/upstream`, which
runs the non-glob `test:plugins:upstream` suite-runner. The new joint
check flagged both specs as never reached.

Append `plugins/integration-test` to each job (which runs
`test:integration:plugins:coverage` with the same `PLUGINS=` env) rather
than spinning up sibling jobs; both specs are self-contained
(`FakeAgent` + `useSandbox`) and slot into the existing harness without
extra service setup.

The axios sandbox previously called `axios.get('/foo')`, which throws
synchronously without producing an http.request, so the spec timed out
waiting for a span. Switch to a full URL pointing at an unused port to
match the existing fetch sandbox; the request can fail and the
instrumentation still ships a span.

* ci(test-optimization): run datadog-plugin-jest unit spec

`packages/datadog-plugin-jest/test/util.spec.js` is matched by
`test:plugins`' glob but no workflow set `PLUGINS=jest` for
`test:plugins:ci`; the existing `integration-jest` matrix runs
`integration-tests/jest/*.spec.js` only, which does not cover the
plugin package's own unit tests. The new joint check flagged it as
never reached.

Add a single `jest:` job invoking the `plugins/test` composite action.
`util.spec.js` is a pure unit test on `getFormattedJestTestParameters`
and `getJestSuitesToRun`, so no service containers or matrix axes are
needed beyond what `plugins/test` already covers (oldest-maintenance
and latest Node).

Restore the three fixture files (`test-to-run.js`, `test-to-skip.js`,
`test-unskippable.js`) under `packages/datadog-plugin-jest/test/fixtures/`
that `getJestSuitesToRun` reads via `isMarkedAsUnskippable`. They were
deleted alongside the other jest plugin specs when those moved to
integration tests, but `util.spec.js` was kept and silently broke
because no CI invocation reached it.

* ci(instrumentation): run 11 orphan instrumentation specs

`packages/datadog-instrumentations/test/{ai,aws-sdk,couchbase,crypto,
express-multi-version,fetch,hono,http-client-options,otel-sdk-trace,
stripe,zlib}.spec.js` are matched by `test:instrumentations`' glob but
no workflow set `PLUGINS=<name>` for `test:instrumentations:ci`, so the
new joint-coverage check in `scripts/verify-exercised-tests.js` flagged
each as never reached by a CI invocation. Add the matching
`instrumentation-<name>` jobs alongside the existing siblings; nine of
the eleven are plain Node unit specs (proxyquire / agent harness) and
need no service containers, so the existing `instrumentations/test`
composite action runs them as-is.

Two specs need a custom job shape on top of that:

1. `couchbase` ships its own libcouchbase: the 3.x line has no prebuilt
   binary for Node 18+ and its bundled sources do not compile under
   modern gcc (missing <cstdint> for std::uint8_t). The composite
   action runs both oldest (18) and latest (24), so neither survives
   the install on its own. Use a matrix that pins one Node version
   per range, mirroring the existing `couchbase` plugin job's `eol`
   (16) for `^3.0.7` and Node 18 for `>=4.2.0`.

2. `http-client-options` listened on `127.0.0.1` only, but
   `http.request(undefined, callback)` resolves to `localhost`, which
   Node 18+ may resolve to `::1` first -- the request then fails with
   `ECONNREFUSED ::1:<port>` before the spec can assert. Bind the test
   server to all interfaces.
This widens the install retry envelope so CI yarn / bun installs
survive more shapes of transient registry failure:

1. `network-timeout 60000` in the repo-root `.yarnrc` doubles yarn's
   per-request timeout from the default 30s; yarn 1.x walks `.yarnrc`
   upward, so the single root entry covers every yarn install in the
   repo tree.

2. Composite install actions use `nick-fields/retry` (pinned in
   `instrumentation.yml`) instead of `|| (sleep N && cmd)`: three
   attempts with a 30s wait between, plus a per-attempt
   `timeout_minutes` cap that bounds a hung install.
…8485)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…#8597)

IPC tests that trigger loadWindow() need more than the default 1000ms
for a Chromium BrowserWindow to load and deliver its span in CI.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Open upstream bug actions/cache#1754: @actions/cache silently exits
non-zero on Windows during cache restore with no error output, failing
the calling step. Symptoms: ~0.6s silent death in setup-bun, setup-node,
or any direct actions/cache use. Affects every job that hits a cold
Windows cache; retrying the job manually almost always succeeds.

- node action: split implementation into node/setup and have node/action
  call it twice (continue-on-error + if failure), so the whole
  composite (setup-node, our version cache, setup-bun) retries once on
  Windows failure. All existing callers and version aliases are
  unchanged.
- datadog-ci action: drop the actions/cache step. @datadog/datadog-ci is
  a bundled package with no transitive deps; the install is fast enough
  that the cache wasn't pulling its weight, and it directly exposed us
  to the same bug.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…tes (#8601)

* chore(deps): bump the ai-and-llm group across 1 directory with 8 updates

Bumps the ai-and-llm group with 8 updates in the /packages/dd-trace/test/plugins/versions directory:

| Package | From | To |
| --- | --- | --- |
| [@langchain/anthropic](https://github.com/langchain-ai/langchainjs) | `1.3.29` | `1.4.0` |
| [@langchain/classic](https://github.com/langchain-ai/langchainjs) | `1.0.32` | `1.0.33` |
| [@langchain/core](https://github.com/langchain-ai/langchainjs) | `1.1.46` | `1.1.47` |
| [@langchain/google-genai](https://github.com/langchain-ai/langchainjs) | `2.1.30` | `2.1.31` |
| [@langchain/langgraph](https://github.com/langchain-ai/langgraphjs/tree/HEAD/libs/langgraph-core) | `1.3.0` | `1.3.1` |
| [@langchain/openai](https://github.com/langchain-ai/langchainjs) | `1.4.5` | `1.4.6` |
| [ai](https://github.com/vercel/ai/tree/HEAD/packages/ai) | `6.0.184` | `6.0.185` |
| [langchain](https://github.com/langchain-ai/langchainjs) | `1.4.0` | `1.4.1` |



Updates `@langchain/anthropic` from 1.3.29 to 1.4.0
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/commits/@langchain/anthropic@1.4.0)

Updates `@langchain/classic` from 1.0.32 to 1.0.33
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/commits/@langchain/classic@1.0.33)

Updates `@langchain/core` from 1.1.46 to 1.1.47
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/compare/@langchain/core@1.1.46...@langchain/core@1.1.47)

Updates `@langchain/google-genai` from 2.1.30 to 2.1.31
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/commits/@langchain/google-genai@2.1.31)

Updates `@langchain/langgraph` from 1.3.0 to 1.3.1
- [Release notes](https://github.com/langchain-ai/langgraphjs/releases)
- [Changelog](https://github.com/langchain-ai/langgraphjs/blob/main/libs/langgraph-core/CHANGELOG.md)
- [Commits](https://github.com/langchain-ai/langgraphjs/commits/@langchain/langgraph@1.3.1/libs/langgraph-core)

Updates `@langchain/openai` from 1.4.5 to 1.4.6
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/commits/@langchain/openai@1.4.6)

Updates `ai` from 6.0.184 to 6.0.185
- [Release notes](https://github.com/vercel/ai/releases)
- [Changelog](https://github.com/vercel/ai/blob/ai@6.0.185/packages/ai/CHANGELOG.md)
- [Commits](https://github.com/vercel/ai/commits/ai@6.0.185/packages/ai)

Updates `langchain` from 1.4.0 to 1.4.1
- [Release notes](https://github.com/langchain-ai/langchainjs/releases)
- [Commits](https://github.com/langchain-ai/langchainjs/compare/@langchain/openai@1.4.0...langchain@1.4.1)

---
updated-dependencies:
- dependency-name: "@langchain/anthropic"
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ai-and-llm
- dependency-name: "@langchain/classic"
  dependency-version: 1.0.33
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
- dependency-name: "@langchain/core"
  dependency-version: 1.1.47
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
- dependency-name: "@langchain/google-genai"
  dependency-version: 2.1.31
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
- dependency-name: "@langchain/langgraph"
  dependency-version: 1.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
- dependency-name: "@langchain/openai"
  dependency-version: 1.4.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
- dependency-name: ai
  dependency-version: 6.0.185
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
- dependency-name: langchain
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ai-and-llm
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: update supported-integrations

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: dd-octo-sts[bot] <200755185+dd-octo-sts[bot]@users.noreply.github.com>
…up/everything-fixture in the npm_and_yarn group across 1 directory (#8596)

Bumps the npm_and_yarn group with 1 update in the /benchmark/sirun/startup/everything-fixture directory: [uuid](https://github.com/uuidjs/uuid).


Updates `uuid` from 9.0.1 to 14.0.0
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](uuidjs/uuid@v9.0.1...v14.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-version: 14.0.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ss 1 directory with 4 updates (#8561)

Bumps the dev-minor-and-patch-dependencies group with 4 updates in the / directory: [axios](https://github.com/axios/axios), [bun](https://github.com/oven-sh/bun), [semver](https://github.com/npm/node-semver) and [yaml](https://github.com/eemeli/yaml).


Updates `axios` from 1.16.0 to 1.16.1
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.16.0...v1.16.1)

Updates `bun` from 1.3.13 to 1.3.14
- [Release notes](https://github.com/oven-sh/bun/releases)
- [Commits](oven-sh/bun@bun-v1.3.13...bun-v1.3.14)

Updates `semver` from 7.7.4 to 7.8.0
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](npm/node-semver@v7.7.4...v7.8.0)

Updates `yaml` from 2.8.4 to 2.9.0
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](eemeli/yaml@v2.8.4...v2.9.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.16.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-minor-and-patch-dependencies
- dependency-name: bun
  dependency-version: 1.3.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: dev-minor-and-patch-dependencies
- dependency-name: semver
  dependency-version: 7.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-and-patch-dependencies
- dependency-name: yaml
  dependency-version: 2.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-minor-and-patch-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
#8594)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
#8564)

The "sends a heap profile on OOM with external process and exits
successfully" test consistently fails on Node 22.22.3 on Linux. With
3 extensions of 15MB each (50MB initial + 45MB), V8 finishes the test
program's 12 x 5MB allocations only by a narrow margin. On Node 22's
V8, the GCs running under tight-heap pressure trigger V8's separate
"Ineffective mark-compacts near heap limit" abort path (independent
of the near-heap-limit callback) before the program completes.

Raising each extension to 20MB gives V8 more breathing room between
OOM events, making individual GCs more likely to be "effective" and
keeping V8's consecutive-ineffective-GC counter from reaching its
threshold. The test still exercises 3 OOM events; only the per-step
size changes.
* Implementation of azure/cosmos integration

* diff reduction

* more diff reduction

* first draft of unit and integration tests

* unit tests working

* testing

* Working integration tests

* linting

* linting

* Some linting, draft of function trigger implementation

* added function trigger instrumentation and tests

* cleanup

* Skip tracing extraneous reads

* Using operation type instead of resource

* move adding error tag to within null check

* temp

* no changes to yarn.lock

* linting and config

* simplify integration test checks

* lint

* add id token perms

* node options on integration test

* node options for non-esm tests

* add timeout waiting for cosmos emulator

* try logging

* try env var to allow emulator connection

* trying http again for non-esm tests

* add cosmosdb to azure-functions test spec

* skip node 18 for testing

* more node skips

* try to refactor azure cosmos import in azure functions integration tests

* use 127.0.0.1 instead of localhost

* remove skipping node 18

* re-lower the minimum supported sdk version

* load azure/cosmos differently

* increase timeout

* restructure checking trace payload

* more debug

* logging

* more debugging

* stronger assertions

* check resources

* fix up trigger tests

* Linting

* trying to fix skip span behavior

* more skip span work

* fixing span skipping

* fix resource in azure functions test

* Responding to reviews, fixing error test

* remove specific version for cosmos package

* linting

* fix use of spread operator

* revert spread operator

* try changing the node options for azure functions cosmos

* normalize resource

* reformatting

* undoing formatting

* Fixing error method in instrumentation

* simplify getting tags

* supported integrations

* Small fixes in index.js

* Unit tests for getResource

* fixing azure functions, use of emulator, and status code tags

* lint

* try disabling cookie

* image digests

* lint

* changing status code to string

* cookie

* proxy agent module

* more packages

* dotnet 8 for azure functions

* crypto

* timeout

* fixing azure functions cosmos test

* teardown of azure cosmos client

* Cleanup

* linting

* Fixing span skip

* use noop to skip account based operations

* Add test for noop

* remove additional file

* modifying getConnectionMode
… 24.16+ (#8604)

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ts (#8616)

* fix(ci): replace setup-bun with npm install to avoid GitHub rate limits

setup-bun hits GitHub Cache API and Releases API rate limits when many
jobs run in parallel. Installing via npm pulls the binary from npm's CDN
instead, avoiding GitHub entirely.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* fix(ci): skip Bun install on unsupported Node.js versions

npm install for bun@1.3.1 runs a postinstall script that fails on
Node.js < 12. Skip the install step on those versions since they
don't use Bun anyway (e.g. integration-guardrails-unsupported).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…p/everything-fixture in the npm_and_yarn group across 1 directory (#8611)

Bumps the npm_and_yarn group with 1 update in the /benchmark/sirun/startup/everything-fixture directory: [qs](https://github.com/ljharb/qs).


Updates `qs` from 6.15.1 to 6.15.2
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.15.1...v6.15.2)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.15.2
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
v1.0.3 fixes a race condition that can cause the API key to never
be outputted.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…stall (#8576)

`FileCoverage.getLineCoverage()` walks `statementMap` only, so
function-declaration lines, `} else {` continuations, and inline
ternary arms never appear in the returned hit map. The `lcovonly`
reporter emits `DA:` records straight from that map, so Codecov's
patch view marks those lines as missing on every PR that touches
them — even when the test run exercised the function or branch
arm — until upstream lands the fix.

Untaken branch arms record as `0` so `LF` totals stay honest. The
patch is idempotent via an inline sentinel and refuses to apply
if the locked upstream code shape changes, so a future
`istanbul-lib-coverage` bump fails the install loudly instead of
silently no-op'ing.

The patch runs in `prepare`, not `postinstall`, and the script
logs to stderr only. Two distinct failure modes drive both
choices:

1. `postinstall` runs on consumer installs and crashes with
   `MODULE_NOT_FOUND` before any in-script guard can fire,
   because the script is not in the `files` allowlist; `prepare`
   is skipped on consumer installs entirely.
2. `prepare` also runs under `npm pack`, where CI captures the
   tarball name via `FILENAME=$(npm pack --silent …)`; output on
   stdout lands inside `$FILENAME` and breaks the downstream
   `mv` / `tar`, so diagnostic output goes to stderr (matching
   `scripts/release/swap-v5-types.js`).

Refs: istanbuljs/istanbuljs#809
@dd-octo-sts dd-octo-sts Bot force-pushed the v5.105.0-proposal branch from 8937fb7 to fe44fbb Compare May 29, 2026 09:58
@dd-octo-sts dd-octo-sts Bot force-pushed the v5.105.0-proposal branch from fe44fbb to 627afc1 Compare May 29, 2026 10:43
@juan-fernandez juan-fernandez requested a review from BridgeAR May 29, 2026 11:02
juan-fernandez
juan-fernandez previously approved these changes May 29, 2026
juan-fernandez and others added 4 commits May 29, 2026 14:45
…ng (#8703)

* fix(mongodb): unify obfuscateQuery sanitizer and speed up query tagging

This replaces the JSON.stringify-with-replacer path for `none` mode with a
single manual walker shared across all three obfuscation modes, so the three
modes no longer diverge in how they classify a value.

It also renders RegExp and Map query values the way the driver serializes
them: a RegExp as its `$regex` / `$options` form and a Map as a document of
its entries. The replacer path dropped both as `{}`, discarding the predicate
from the span tag.

The walker is faster than the per-node replacer callback across the common
query shapes (node 24.15.0, V8 13.6, 300k x 11 trials):

  bigint id        227 ns/op -> 106 ns/op  (~54%)
  deep nested      622 ns/op -> 474 ns/op  (~24%)
  ObjectId field   276 ns/op -> 220 ns/op  (~20%)
  binary field     323 ns/op -> 103 ns/op  (~68%)

Plain queries without these shapes stay on the direct stringify fast path and
are unchanged.

* fix(mongodb): keep a null toJSON result as null in none mode

A field whose `toJSON()` returns `null` was dropped from the query tag
because the null result was routed through the leaf classifier, which
returns `undefined` for non-primitives and so omitted the key. An invalid
Date (`new Date(NaN).toJSON()` returns `null`) tagged `{ expiresAt, big: 1n }`
as `{"big":"1"}` and produced no tag at all at the top level.

JSON.stringify keeps such a result as `null` (in objects, in arrays, and at
the top level); the walker now matches that. Only function / symbol /
undefined results still drop the key.
#8513)

* perf(format): split addTag into typed helpers to kill throwaway {} allocations

`addTag(meta, metrics, key, value)` dispatched on `typeof value` to
pick between the two slots. Twelve call sites in `span_format.js`
passed an empty `{}` for the slot they did not want -- roughly 50 to
300 throwaway objects per request -- only so the polymorphic helper
could ignore them. Typed `addStringTag` / `addNumberTag` /
`addBooleanTag` / `addMixedTag` helpers replace the dispatch; intent
lives in the helper picked at the call site.

`extractTags` also switches from `Object.entries(tags)` to
`Object.keys(tags)` with an inner `tags[tag]` lookup, dropping the
`[key, value]` pair-array allocation per tag.

* perf(format): inline known-type tag dispatch in span_format hot path

`extractTags` ran `addMixedTag` for the five trailing always-known-type
tags (`language`, `process_id`, `_sampling_priority_v1`, `_dd.origin`,
`_dd.hostname`), and `extractChunkTags` did the same for the optional
process tag. Each call paid the polymorphic `typeof value` switch
inside `addMixedTag` for nothing -- the type is pinned at the call
site. Route through the typed helpers, or directly to the meta /
metrics slot when both key and value are constants.

`extractChunkTags` only fires for the first span in a chunk. The
caller now skips the call entirely for the N-1 non-first spans per
flush instead of taking the bailout inside the callee.
`Object.entries(_trace.tags)` becomes `Object.keys` + indexed lookup
in the same shape `extractTags` already uses.

Bench (redis GET shape: 10 user tags, 1 chunk tag, sampling priority
set; n=1_000_000 x 7 trials x 3 runs, drop best+worst; Node 24.15.0 /
V8 13.6.233.17):

* baseline ~783 ns/op median (trimmed mean ~798)
* patched  ~688 ns/op median (trimmed mean ~701)
* delta    ~95 ns/op (~12 %) per format(span)

* perf(format): inline scalar-tag writes and pin formatted-span shape

Two coordinated pieces on every Express span:

1. `formatSpan` built the result object literal without slots for the
   optional `service`, `type`, and `span_events` fields. V8 saw a
   fresh hidden-class transition the first time each appeared, so
   spans with and without those properties used different shapes and
   downstream reads (`encode/0.4.js`, agentless JSON, payload-size
   accounting) went polymorphic. Pinning all three to `undefined` up
   front locks one shape per format; the encoders already gate on
   truthy values so the wire output stays byte-identical.

2. `extractTags`' switch routed every ordinary string / number /
   boolean tag through `addMixedTag` -- a per-tag function frame plus
   a typeof dispatch -- even though the call site iterates a plain
   user-tag object where almost all values are scalar. The special
   cases (`service.name`, `span.type`, `resource.name`,
   `http.status_code`, `analytics.event`, `HOSTNAME_KEY` / `MEASURED`)
   and the trailing assignments (`language`, `process_id`, sampling
   priority, origin, hostname) likewise went through `addStringTag` /
   `addNumberTag` for what is a single conditional write. The typed
   helpers and the `map` lookup table are gone; the bodies are now
   expanded at each call site and a single `addMixedTag` fallback
   covers only non-scalar values and `extractError`.

`extractRootTags` and `extractChunkTags` get the same treatment for
`SAMPLING_*_DECISION` / `TOP_LEVEL_KEY` and chunk tag strings. Chunk
tags are always strings in production (`_dd.p.*`, `baggage.*`) so the
string branch is inlined; non-string values still fall through to
`addMixedTag` for parity.

`setSingleSpanIngestionTags` is inlined in the same shape (typeof
guard + direct metric write) and the misnamed `span` parameter is
renamed to `formattedSpan` so the function reads correctly at the
call site.

A `deepStrictEqual` snapshot of a representative HTTP-server span is
added to `span_format.spec.js` as a regression guard for the
byte-identical contract, plus tests for the recursive `addMixedTag`
branch and chunk-tag truncation that the previous coverage missed.

Bench (Express server-shape: 10 user tags, 2 metric tags, `_dd.p.dm`
+ `_dd.p.tid` chunk tags, sampling priority 1, n=1_000_000 x 7 trials
x 5 runs, drop best+worst; Node 24.15.0 / V8 13.6.233.17):

* baseline ~295 ns/op median
* patched  ~209 ns/op median
* delta    ~86 ns/op (~29 %) per format(span)

* fix(format): coerce error tag values to meta strings

A user-set `span.error.type` / `span.error.message` / `span.error.stack`
of any non-string type used to fall through the `extractTags` switch
into the default branch, where `addMixedTag`'s `typeof` dispatch routed
numbers to `metrics` and booleans / objects to `metrics` via
`String(value)`. The agent and backend both treat the three error meta
fields as strings, so the tag would silently disappear from the error
report on every span where a custom `Error` subclass or user code set a
non-string value.

The error-tag cases now write directly to `meta` through a new
`writeErrorMeta` helper that coerces and truncates at the format
boundary, and `extractError` routes the three `Error` fields through
the same helper so subclasses that override `name` / `message` /
`stack` with non-string values get the same shape.

Drop the `Number.isNaN` guards on `_dd.sampling_priority`,
`_dd.rule_psr`, `_dd.limit_psr`, `_dd.agent_psr`,
`_dd.span_sampling.rule_rate`, and `_dd.span_sampling.max_per_second`.
`NaN` cannot reach these fields by construction:

1. `Sampler` runs `BigInt(Math.floor(rate * MAX_TRACE_ID))` in its
   constructor, which throws on `NaN` before any rule is stored.
2. `RateLimiter#effectiveRate` only returns finite numbers or `1` / `0`.
3. The sampling priority is gated by `priority_sampler#validate` and
   the propagation extractors' `Number.isInteger` check.

Either the field is a finite number or `undefined`; the `typeof
=== 'number'` gate is the only real case left.

Drive-by fix:

* Reflow the `span_events` JSDoc into a dedicated `SpanEvent` typedef
  so the file stays under the 120-column limit.

* test(format): cover inlined truncation branches and error coercion

The three perf commits inlined truncation into `extractTags`,
`extractChunkTags`, and the error-tag cases, and the preceding fix
added `writeErrorMeta`. The spec did not exercise the new lines:

1. `span.type`, `resource.name`, and `http.status_code` each carry a
   dedicated inlined truncation branch in the switch — pin all three
   so a refactor that collapses them surfaces here.
2. Origin and hostname meta values have their own truncation gates
   outside the switch — pin both.
3. The chunk-tag for-loop has separate key- and value-truncation
   branches; add a second tag with a short key + overlong value so
   both branches run.
4. The `addMixedTag` default branch routes `URL` to metrics via
   `value.toString()` next to `Buffer`; the Buffer half was already
   covered, the URL half is now pinned so a future tightening that
   drops the `isUrl` check surfaces here.
5. Three new error-coercion specs cover non-string `setTag` values,
   `null` / `undefined` skip, and overlong-stack truncation; two more
   cover `extractError` against custom `Error` subclasses with
   non-string `name` / `message` / `stack`.

Replace the stale `Number.NaN` injection in the root-tag decision spec
with an `undefined` injection. `Sampler.rate()` and
`RateLimiter.effectiveRate()` cannot return `NaN`, so the previous
test exercised a path the new code no longer guards against; the
`undefined` case is the only real branch left to pin.
* perf(encode): tighten msgpack dispatch and debug-log allocation

Four small wins on the encode and debug-log paths:

1. `MsgpackEncoder#encodeValue` dispatches `string` first. The string
   arm covers tag values and map keys; the prior order paid four
   `switch` comparisons before reaching it.
2. `MsgpackEncoder#encodeMap` emits keys via `encodeString` directly.
   `Object.keys` only yields strings, so the typeof re-dispatch is
   dead work.
3. `AgentEncoder.encode` hoists the `DD_TRACE_ENCODING_DEBUG`
   hex-dump formatter to a module-level function. The closure used
   to allocate per encode whenever the debug switch was on.
4. `memoizedLogDebug` switches to printf-style. The substitution only
   runs when the debug channel has subscribers.

`log` now forwards trailing arguments to a function delegate so the
formatter in (3) can take `bytes`, `start`, `end` as parameters
instead of capturing them via closure.

* perf(encode): fold msgpack primitives onto MsgpackChunk

The tracer dispatched every byte-layout write through three layers:
`subclass._encodeX(bytes, value)` → the base wrapper → the
`MsgpackEncoder` instance. The wrappers existed so msgpack could be
swapped at runtime, which never happened and was never planned.

`MsgpackChunk` now owns the byte-layout primitives directly. Call
sites encode straight into the chunk; the eight base-class wrappers
and the `MsgpackEncoder` class go away. `DataStreamsWriter`, the one
external caller of the deleted `msgpack.encode(payload)` method,
imports the free `encode` function that exposes the same recursive
dispatcher.

* perf(msgpack): right-size MsgpackChunk to its actual workload

Initial capacity drops from 2 MiB to 1 MiB. Each `AgentEncoder` holds
two `MsgpackChunk` instances and the datastreams writer adds one more,
so the previous default cost every tracer-loaded process a fixed
4 - 6 MiB regardless of payload size. A representative HTTP trace
serializes well under 100 KiB, but keeping a megabyte of headroom
avoids the first resize on bursts of larger spans (long URLs, JSON
event payloads) so the typical request never copies through an
intermediate buffer.

`reserve` doubles the capacity on overflow instead of rounding up to
the next `minSize` multiple. Worst-case burst growth from 1 MiB to
the 8 MiB soft flush limit takes the same number of resizes as the
old 2 MiB-aligned walk but reaches the larger sizes earlier, cutting
the time spent copying through intermediate buffers.

`reset` is the new flush signal: it zeros the cursor and counts
consecutive flushes whose peak length stayed under a quarter of the
current buffer. After 32 such quiet flushes the chunk halves toward
the `minSize` floor. One above-threshold peak resets the streak, so
long-lived encoders give memory back during idle periods but hold
on to the warmed buffer through sustained traffic.

* perf(encode): pre-fuse the `error: 0` and `error: 1` payloads

Every encoded span emits a `[KEY_ERROR][writeIntOrFloat(span.error)]`
pair, and `span.error` is `0` or `1` on the overwhelming majority of
spans — only a handful of plugins use any other numeric value, and the
tracer never stores anything else there. The hot loop therefore paid
two `MsgpackChunk.reserve` calls, two memory writes, and one trip
through `writeIntOrFloat`'s magnitude-detection branches for what is
effectively a constant on every span.

Two precomputed `[KEY_ERROR, fixint]` constants (7 bytes each) collapse
the common case to a single `bytes.set`. The else branch keeps the
existing variable-value path so the rare non-{0,1} values still emit
the shortest valid encoding.

* perf(encode): bypass the string cache for values over 1 KiB

`_encodeString` and `#encodeMetaEntries` looked up every value in
`_stringMap` before emitting it, including the multi-KiB strings the
tracer produces from stringified `span_events`, stack traces, full SQL
statements, and large query bodies. Those values are essentially
unique per span on real traffic, so the cache hit rate is near zero
and the lookup cost is paid for nothing. The
`encoders-0.4-events-legacy` sirun scenario picked the regression up
on a realistic trace fixture.

Values longer than `STRING_CACHE_BYPASS_LIMIT` (1 KiB) now write
directly through `MsgpackChunk.write`. The threshold sits well above
the routine span-tag distribution (URLs, methods, IPs, resource names
all comfortably below 256 bytes) and well below the size where the
per-call hash dominates the per-call write. Short, repeating tag
values still hit the cache and pay nothing.

Bench (`benchmark/sirun/encoding/index.js` adapted: 30-span trace,
5 000 iterations, 7 trials drop best+worst; Node 24.15.0):

* `encoder=0.4 events=legacy` master 324 ms -> patched 341 ms
  (was 346 ms before this commit, -1.5 %)
* `encoder=0.4 events=none`   master  50 ms -> patched  47 ms (-7.6 %)
* `encoder=0.5 events=none`   master  30 ms -> patched  29 ms (-5.5 %)

`encoder=0.5 events=legacy` still regresses because the 0.5 wire ships
strings as indices and cannot bypass the lookup.

Wire output is unchanged: `bytes.write` emits the same fixstr / str32
bytes that `_cacheString` would have stored, just without the cache
side effect.

* test(encode): exercise agentless-JSON soft-limit flush via constructor

The flush-on-soft-limit test was reaching into `encoder._estimatedSize`
to push the encoder over the threshold. The reach-in only existed
because the 8 MiB soft limit was a module-local constant, so the test
had no other way to trigger the branch without actually encoding a
multi-megabyte payload.

Add a `softLimit` constructor parameter to `AgentlessJSONEncoder` —
mirroring the same hook on the v0.4/v0.5 `AgentEncoder` — and rewrite
the test to construct a tiny-limit encoder. The reach-in goes away, the
soft-limit branch is now reachable from public API for any caller that
wants to bound payload size for tests or for memory-constrained
environments, and production behavior is unchanged when the parameter
is omitted.

* perf(encode): extend per-span block past service into the start/duration keys

Almost every real span carries `error: 0` / `error: 1` and a nanosecond
`start` ≥ 2³². When both hold the encoder can fuse the error key+fixint,
the `start` key + 0xCF type byte + 8-byte timestamp, and the `duration`
key into the same `bytes.reserve` that already covers the map header,
optional `type`, the three IDs, and name/resource/service. The new path
collapses up to four extra reserves per span (one each for the error
key+value, the start key, the start value's u64 dispatch, and the
duration key) into the existing one.

Spans that don't fit the assumption (synthetic test data with small
`start`, rare non-binary error flags) drop back to the per-field emits
so each integer still picks the shortest msgpack encoding — keeping the
existing wire-format guarantees for those inputs.

`KEY_START_PREFIX` is the precomputed `[KEY_START, 0xCF]` fusion. The
8-byte timestamp lands via two `Buffer.writeUInt32BE` calls; the hi/lo
split matches what `writeLong` would have done.

* perf(encode): inline the fixint fast path in #encodeMetaEntries

The numeric branch of the meta-map writer used to pay two `reserve`
calls per entry: one for the key prefix, one inside `writeIntOrFloat`
for the value byte. The metrics map is mostly small positive integers
(`_sampling_priority_v1`, `_dd.measured`, attribute counts, ms timings
that fit in 0..127), so every one of those entries hits the fixint
fast path inside `writeIntOrFloat` anyway — but only after paying a
second reserve and a three-level branch chain.

Speculate the fixint case at the call site: reserve `keyEntryLen + 1`
up front, copy the key, and write the value byte directly. When the
speculation misses (large counts, floats, signed numbers), rewind the
speculative byte and fall back to the full writer so the wire still
picks the shortest valid encoding.

* docs(encode): note that span_events stringification is memoizable

Both formatters re-stringify `span_events` from scratch on every encode
call even when the underlying event array survives across encode cycles
(retries, re-emission paths). The events=legacy hot path is currently
bound by raw memory bandwidth from those re-stringifications, not the
cache lookups.

Leave the WeakMap memoization out of this branch — it interacts with
the formatter / span lifecycle in ways that warrant their own change.
Drop a pointer at the two call sites so the next reader knows where the
remaining headroom lives. No production behavior change.

* Apply suggestions from code review

Co-authored-by: Ruben Bridgewater <ruben@bridgewater.de>

* refactor(msgpack): drop dead writeFixMap and writeFixArray default

`writeFixMap` has no caller -- `_encodeMap` and the v0.5 encoder go
through `writeMapPrefix` (map32) regardless of size. Same shape for
`writeFixArray`'s `= 0` default; its only caller passes the length
explicitly.

* test(encode): cover msgpack chunk primitives and the 0.4 fallback branch

Pin the patch lines codecov flagged as uncovered:

1. `MsgpackChunk.writeNull` / `writeBoolean` / `writeBin` (bin32 path
   for byteLength >= 65 536) / `writeSigned` (int8 the encoder never
   reaches via `writeIntOrFloat`) / `writeNumber` NaN coercion. The
   spec exercises the rest of the public `writeX` surface in the same
   pass so the boundaries between fixint / uint8 / uint16 / uint32 /
   uint64 and the signed counterparts are pinned.
2. `msgpack/encode` dispatcher arms for `null`, `boolean`, `symbol`,
   the `default` arm (function / undefined), and `array.length >= 16`
   (array32 prefix).
3. `AgentEncoder._encode`'s non-fuseTail fallback for `error === 1`
   and unusual error flags -- the synthetic-input path the comment
   on the fused-tail block calls out.

* perf(encode): fuse the per-span head block on the v0.5 wire

Every v0.5 span used to pay seven separate `bytes.reserve` calls for
its fixed-size prefix: one for the `0x9C` fixarray marker, three for
the service / name / resource indices, and three for the trace / span
/ parent uint64 ids. Pre-resolve the three string indices, then write
the whole 43-byte head block (1 + 5 × 3 + 9 × 3) under one reserve.

The v0.5 wire is positional — no map keys — so the fuse is simpler
than the v0.4 equivalent: no key bytes to concatenate, and the four
fixed-shape elements (marker + three indices + three ids) tile the
block exactly. The remaining per-span fields (`start`, `duration`,
`error`, `meta`, `metrics`, `type`) keep their per-call writes because
their byte sizes depend on the value.

While here, refactor `_cacheString` so it returns the resolved index
instead of just having the side effect. The head fuse uses
`stringMap[value] ?? this._cacheString(value)` to resolve indices
without re-fetching, and `_encodeString` collapses onto the same
pattern. `_reset()` (inherited from 0.4) calls `_cacheString('')` for
the seeding side effect and ignores the return value — no behavior
change there.

Two new private helpers (`#writeIndexAt`, `#writeIdAt`) keep the
fused block readable; both are inlinable single-shot writes the
encoder code calls directly into the pre-reserved buffer.

Bench (`benchmark/sirun/encoding/index.js`, 30-span Express-request
trace, 5 000 iterations per trial, 7 trials drop best+worst, Node
24.15.0; same fixture on both checkouts, only the encoder source
differs):

* `encoder=0.5 events=none`   master  98 ms -> patched  77 ms (-21 %)
* `encoder=0.5 events=legacy` master 395 ms -> patched 366 ms ( -7 %)
* `encoder=0.4 *` unchanged within noise (the v0.4 hot path is not
  touched).

* perf(encode): speculate the fixint fast path in v0.5 _encodeMap

The v0.5 `_encodeMap` override used to pay two `bytes.reserve` calls
per numeric entry — one for the key (5-byte uint32 index) and one
inside `writeIntOrFloat` for the value byte. The metrics map is mostly
small positive integers (`_sampling_priority_v1`, `_dd.measured`,
attribute counts), so every one of those entries hits the fixint fast
path inside `writeIntOrFloat` anyway, but only after paying that
second reserve and a three-level branch chain.

Speculate the fixint case at the call site: reserve `5 + 1` up front,
write the key index, then write the value byte directly. Speculation
misses rewind the speculative byte and fall back to the full encoder
so the wire still picks the shortest valid encoding. Mirrors the same
move the v0.4 `#encodeMetaEntries` made for the meta hot path.

String entries collapse onto the same shape: both halves are uint32
indices on the v0.5 wire (5 bytes each), so the key and value emit
under a single 10-byte reserve. Non-string / non-number entries skip
early — same filter the previous loop applied implicitly.

Bench (`benchmark/sirun/encoding/index.js`, 30-span Express-request
trace, 5 000 iterations per trial, 7 trials drop best+worst, Node
24.15.0):

* `encoder=0.5 events=none`   master  100 ms -> patched  76 ms (-24 %)
* `encoder=0.5 events=legacy` master  397 ms -> patched 364 ms ( -8 %)

Wire output is unchanged.

* fix(msgpack): honour Buffer byteOffset in chunk views

`Buffer.allocUnsafe(size)` returns a pooled slice whose `byteOffset` is
non-zero when `size <= Buffer.poolSize / 2`. The previous
`new DataView(this.buffer.buffer)` and `new Uint8Array(this.buffer.buffer,
sourceStart, ...)` shapes addressed the shared 8 KiB slab from offset 0
instead of the chunk's own window, so `writeFloat`, `writeBigInt`, and
`MsgpackChunk.copy` either wrote into a sibling consumer's bytes or
returned a stale slice.

The 2048-byte prefix chunk is the first caller small enough to be
pool-allocated; the default 1 MiB chunk always lands at
`byteOffset === 0`, so the bug stayed latent on master.
BridgeAR
BridgeAR previously approved these changes May 29, 2026
@BridgeAR BridgeAR enabled auto-merge (rebase) May 29, 2026 14:55
auto-merge was automatically disabled May 29, 2026 15:09

Rebase failed

juan-fernandez
juan-fernandez previously approved these changes May 29, 2026
@dd-octo-sts dd-octo-sts Bot dismissed stale reviews from juan-fernandez and BridgeAR via 1d6f5a3 May 29, 2026 15:28
juan-fernandez
juan-fernandez previously approved these changes May 29, 2026
BridgeAR and others added 3 commits May 29, 2026 16:31
…ion to client spans (#8407) (#8706)

This reverts commit 55ed50f.

stripping the outbound query string unconditionally and instead redacted it
with `queryStringObfuscation`. For high-traffic clients with variable query
strings (UUIDs, ISO timestamps, free-text search), retaining the query string
— even fully redacted — reintroduced a large source of `http.url` cardinality
that the previous strip-all behaviour did not have. A customer hit exactly this
explosion.

Reverting restores the pre-#8407 client behaviour (query string stripped from
`http.url`, no `http.endpoint` on client spans) while we decide whether the
parity feature is worth the cardinality cost and, if so, how to bound it
(e.g. type-token redaction rather than verbatim values).

The server side is untouched by this revert.

Refs: #2022
…ebpack in the npm_and_yarn group across 1 directory (#8705)

Bumps the npm_and_yarn group with 1 update in the /integration-tests/webpack directory: [axios](https://github.com/axios/axios).


Updates `axios` from 1.15.2 to 1.16.0
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](axios/axios@v1.15.2...v1.16.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-version: 1.16.0
  dependency-type: direct:production
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@BridgeAR BridgeAR closed this May 29, 2026
@BridgeAR BridgeAR deleted the v5.105.0-proposal branch May 29, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.