Skip to content

feat(data-pipeline)!: export client-computed span stats as OTLP trace metrics#2067

Open
mabdinur wants to merge 10 commits into
mainfrom
munir/otlp-trace-metrics
Open

feat(data-pipeline)!: export client-computed span stats as OTLP trace metrics#2067
mabdinur wants to merge 10 commits into
mainfrom
munir/otlp-trace-metrics

Conversation

@mabdinur

@mabdinur mabdinur commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Overview

Adds native OTLP trace-metrics export to libdd-data-pipeline. The span concentrator's per-cell stats are encoded as a traces.span.sdk.metrics.duration delta histogram and POSTed to a configured /v1/metrics endpoint on a 10s cadence. This is the shared Rust implementation consumed by dd-trace-py and other Datadog tracers — tracers only supply configuration.

Non-obvious details for reviewers

  • count/sum/min/max are exact (from per-cell accumulators, ns→s), not reconstructed from the DDSketch. The bucket distribution is projected from the DDSketch onto a fixed 17-bucket layout matching the OTel spanmetrics-connector defaults so payloads are comparable across tracers.
  • With OTLP metrics enabled, check_agent_info still runs V1 protocol negotiation but skips stats enable/disable — the concentrator starts unconditionally and is not affected by agent info.
  • _dd.stats_computed: "true" is added to every outbound OTLP trace ResourceSpans (and Datadog-Client-Computed-Stats: yes to the HTTP request) when stats are enabled. The Agent's OTLP receiver checks this attribute to skip its concentrator, preventing double-counted APM metrics. Set unconditionally regardless of OTel semantics mode. Both signals are backwards compatible with released Agents.
  • grpc_method is stored in GroupedStats (value side), not in FixedAggregationKey. This keeps it out of Hash/PartialEq so gRPC spans with different methods merge into one agent stats bucket — matching pre-existing behaviour. The method is still surfaced on OtlpExactGroup for OTLP data points. No breaking changes.

Testing: 154 nextest tests pass across libdd-trace-stats and libdd-data-pipeline. Companion: DataDog/dd-trace-py#18354.

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 2645 documentation warning(s) found

📦 libdd-data-pipeline - 1150 warning(s)

📦 libdd-ddsketch - 8 warning(s)

📦 libdd-trace-stats - 811 warning(s)

📦 libdd-trace-utils - 676 warning(s)


Updated: 2026-06-18 19:16:32 UTC | Commit: 27b08f6 | missing-docs job results

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Clippy Allow Annotation Report

Comparing clippy allow annotations between branches:

  • Base Branch: origin/main
  • PR Branch: origin/munir/otlp-trace-metrics

Summary by Rule

Rule Base Branch PR Branch Change
unwrap_used 4 5 ⚠️ +1 (+25.0%)
Total 4 5 ⚠️ +1 (+25.0%)

Annotation Counts by File

File Base Branch PR Branch Change
libdd-data-pipeline/src/otlp/metrics.rs 0 1 ⚠️ +1 (N/A)
libdd-data-pipeline/src/trace_exporter/mod.rs 2 2 No change (0%)
libdd-ddsketch/src/lib.rs 2 2 No change (0%)

Annotation Stats by Crate

Crate Base Branch PR Branch Change
clippy-annotation-reporter 5 5 No change (0%)
datadog-ffe-ffi 1 1 No change (0%)
datadog-ipc 22 21 ✅ -1 (-4.5%)
datadog-live-debugger 4 4 No change (0%)
datadog-live-debugger-ffi 10 10 No change (0%)
datadog-profiling-replayer 4 4 No change (0%)
datadog-sidecar 45 45 No change (0%)
libdd-common 13 13 No change (0%)
libdd-common-ffi 12 12 No change (0%)
libdd-data-pipeline 5 6 ⚠️ +1 (+20.0%)
libdd-ddsketch 2 2 No change (0%)
libdd-dogstatsd-client 1 1 No change (0%)
libdd-profiling 13 13 No change (0%)
libdd-remote-config 3 3 No change (0%)
libdd-telemetry 20 20 No change (0%)
libdd-tinybytes 4 4 No change (0%)
libdd-trace-normalization 2 2 No change (0%)
libdd-trace-obfuscation 3 3 No change (0%)
libdd-trace-stats 1 1 No change (0%)
libdd-trace-utils 11 12 ⚠️ +1 (+9.1%)
Total 181 182 ⚠️ +1 (+0.6%)

About This Report

This report tracks Clippy allow annotations for specific rules, showing how they've changed in this PR. Decreasing the number of these annotations generally improves code quality.

@datadog-datadog-prod-us1-2

datadog-datadog-prod-us1-2 Bot commented Jun 1, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 84.33%
Overall Coverage: 73.86% (+0.48%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3bd3773 | Docs | Datadog PR Page | Give us feedback!

@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

⚠️ 14 issue(s) found, showing only errors (advisories, bans, sources)

📦 libdd-data-pipeline - 5 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:218:1
    │
218 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
    │
    ├ ID: RUSTSEC-2026-0097
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
    ├ It has been reported (by @lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
      
      - The `log` and `thread_rng` features are enabled
      - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
      - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
      - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
      - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
      
      `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
    ├ Announcement: https://github.com/rust-random/rand/pull/1763
    ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
    ├ rand v0.8.5
      ├── libdd-common v4.2.0
      │   ├── libdd-capabilities-impl v2.0.0
      │   │   ├── libdd-data-pipeline v6.0.0
      │   │   ├── libdd-shared-runtime v1.0.0
      │   │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │   │   ├── libdd-telemetry v5.0.1
      │   │   │   │   └── libdd-data-pipeline v6.0.0 (*)
      │   │   │   └── libdd-trace-stats v5.0.0
      │   │   │       └── libdd-data-pipeline v6.0.0 (*)
      │   │   ├── libdd-trace-stats v5.0.0 (*)
      │   │   └── libdd-trace-utils v8.0.0
      │   │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-data-pipeline v6.0.0 (*)
      │   ├── libdd-dogstatsd-client v3.0.0
      │   │   └── libdd-data-pipeline v6.0.0 (*)
      │   ├── libdd-shared-runtime v1.0.0 (*)
      │   ├── libdd-telemetry v5.0.1 (*)
      │   ├── libdd-trace-obfuscation v4.0.0 (*)
      │   ├── libdd-trace-stats v5.0.0 (*)
      │   └── libdd-trace-utils v8.0.0 (*)
      ├── (dev) libdd-data-pipeline v6.0.0 (*)
      ├── (dev) libdd-ddsketch v1.0.1
      │   ├── libdd-data-pipeline v6.0.0 (*)
      │   ├── libdd-telemetry v5.0.1 (*)
      │   └── libdd-trace-stats v5.0.0 (*)
      ├── (dev) libdd-trace-normalization v2.0.0
      │   ├── libdd-data-pipeline v6.0.0 (*)
      │   └── libdd-trace-utils v8.0.0 (*)
      ├── (dev) libdd-trace-stats v5.0.0 (*)
      ├── libdd-trace-utils v8.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── libdd-data-pipeline v6.0.0 (*)
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v8.0.0 (*)

error[vulnerability]: Name constraints for URI names were incorrectly accepted
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:245:1
    │
245 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0098
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0098
    ├ Name constraints for URI names were ignored and therefore accepted.
      
      Note this library does not provide an API for asserting URI names, and URI name constraints are otherwise not implemented.  URI name constraints are now rejected unconditionally.
      
      Since name constraints are restrictions on otherwise properly-issued certificates, this bug is reachable only after signature verification and requires misissuance to exploit.
      
      This vulnerability is identified as [GHSA-965h-392x-2mh5](https://github.com/rustls/webpki/security/advisories/GHSA-965h-392x-2mh5). Thank you to @1seal for the report.
    ├ Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   ├── libdd-data-pipeline v6.0.0
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   ├── libdd-telemetry v5.0.1
      │   │       │   │   │   └── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   └── libdd-trace-stats v5.0.0
      │   │       │   │       └── libdd-data-pipeline v6.0.0 (*)
      │   │       │   ├── libdd-trace-stats v5.0.0 (*)
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-dogstatsd-client v3.0.0
      │   │       │   └── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-shared-runtime v1.0.0 (*)
      │   │       ├── libdd-telemetry v5.0.1 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:245:1
    │
245 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0099
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0099
    ├ Permitted subtree name constraints for DNS names were accepted for certificates asserting a wildcard name.
      
      This was incorrect because, given a name constraint of `accept.example.com`, `*.example.com` could feasibly allow a name of `reject.example.com` which is outside the constraint.
      This is very similar to [CVE-2025-61727](https://go.dev/issue/76442).
      
      Since name constraints are restrictions on otherwise properly-issued certificates, this bug is reachable only after signature verification and requires misissuance to exploit.
      
      This vulnerability is identified as [GHSA-xgp8-3hg3-c2mh](https://github.com/rustls/webpki/security/advisories/GHSA-xgp8-3hg3-c2mh). Thank you to @1seal for the report.
    ├ Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   ├── libdd-data-pipeline v6.0.0
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   ├── libdd-telemetry v5.0.1
      │   │       │   │   │   └── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   └── libdd-trace-stats v5.0.0
      │   │       │   │       └── libdd-data-pipeline v6.0.0 (*)
      │   │       │   ├── libdd-trace-stats v5.0.0 (*)
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-dogstatsd-client v3.0.0
      │   │       │   └── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-shared-runtime v1.0.0 (*)
      │   │       ├── libdd-telemetry v5.0.1 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:245:1
    │
245 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0104
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0104
    ├ A panic was reachable when parsing certificate revocation lists via [`BorrowedCertRevocationList::from_der`]
      or [`OwnedCertRevocationList::from_der`].  This was the result of mishandling a syntactically valid empty
      `BIT STRING` appearing in the `onlySomeReasons` element of a `IssuingDistributionPoint` CRL extension.
      
      This panic is reachable prior to a CRL's signature being verified.
      
      Applications that do not use CRLs are not affected.
      
      Thank you to @tynus3 for the report.
    ├ Solution: Upgrade to >=0.103.13, <0.104.0-alpha.1 OR >=0.104.0-alpha.7 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   ├── libdd-data-pipeline v6.0.0
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   ├── libdd-telemetry v5.0.1
      │   │       │   │   │   └── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   └── libdd-trace-stats v5.0.0
      │   │       │   │       └── libdd-data-pipeline v6.0.0 (*)
      │   │       │   ├── libdd-trace-stats v5.0.0 (*)
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       ├── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-dogstatsd-client v3.0.0
      │   │       │   └── libdd-data-pipeline v6.0.0 (*)
      │   │       ├── libdd-shared-runtime v1.0.0 (*)
      │   │       ├── libdd-telemetry v5.0.1 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Denial of Service via Stack Exhaustion
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:286:1
    │
286 │ time 0.3.41 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0009
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0009
    ├ ## Impact
      
      When user-provided input is provided to any type that parses with the RFC 2822 format, a denial of
      service attack via stack exhaustion is possible. The attack relies on formally deprecated and
      rarely-used features that are part of the RFC 2822 format used in a malicious manner. Ordinary,
      non-malicious input will never encounter this scenario.
      
      ## Patches
      
      A limit to the depth of recursion was added in v0.3.47. From this version, an error will be returned
      rather than exhausting the stack.
      
      ## Workarounds
      
      Limiting the length of user input is the simplest way to avoid stack exhaustion, as the amount of
      the stack consumed would be at most a factor of the length of the input.
    ├ Announcement: https://github.com/time-rs/time/blob/main/CHANGELOG.md#0347-2026-02-05
    ├ Solution: Upgrade to >=0.3.47 (try `cargo update -p time`)
    ├ time v0.3.41
      └── tracing-appender v0.2.3
          └── libdd-log v1.0.0
              └── (dev) libdd-data-pipeline v6.0.0

advisories FAILED, bans ok, sources ok

📦 libdd-ddsketch - 1 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:45:1
   │
45 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
   │
   ├ ID: RUSTSEC-2026-0097
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
   ├ It has been reported (by @lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
     
     - The `log` and `thread_rng` features are enabled
     - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
     - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
     - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
     - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
     
     `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
   ├ Announcement: https://github.com/rust-random/rand/pull/1763
   ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
   ├ rand v0.8.5
     └── (dev) libdd-ddsketch v1.0.1

advisories FAILED, bans ok, sources ok

📦 libdd-trace-stats - 4 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:193:1
    │
193 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
    │
    ├ ID: RUSTSEC-2026-0097
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
    ├ It has been reported (by @lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
      
      - The `log` and `thread_rng` features are enabled
      - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
      - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
      - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
      - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
      
      `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
    ├ Announcement: https://github.com/rust-random/rand/pull/1763
    ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
    ├ rand v0.8.5
      ├── (dev) libdd-common v4.2.0
      │   ├── libdd-capabilities-impl v2.0.0
      │   │   ├── libdd-shared-runtime v1.0.0
      │   │   │   └── libdd-trace-stats v5.0.0
      │   │   ├── libdd-trace-stats v5.0.0 (*)
      │   │   └── libdd-trace-utils v8.0.0
      │   │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-shared-runtime v1.0.0 (*)
      │   ├── libdd-trace-obfuscation v4.0.0 (*)
      │   ├── libdd-trace-stats v5.0.0 (*)
      │   └── libdd-trace-utils v8.0.0 (*)
      ├── (dev) libdd-ddsketch v1.0.1
      │   └── libdd-trace-stats v5.0.0 (*)
      ├── (dev) libdd-trace-normalization v2.0.0
      │   └── libdd-trace-utils v8.0.0 (*)
      ├── (dev) libdd-trace-stats v5.0.0 (*)
      ├── libdd-trace-utils v8.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v8.0.0 (*)

error[vulnerability]: Name constraints for URI names were incorrectly accepted
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:220:1
    │
220 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0098
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0098
    ├ Name constraints for URI names were ignored and therefore accepted.
      
      Note this library does not provide an API for asserting URI names, and URI name constraints are otherwise not implemented.  URI name constraints are now rejected unconditionally.
      
      Since name constraints are restrictions on otherwise properly-issued certificates, this bug is reachable only after signature verification and requires misissuance to exploit.
      
      This vulnerability is identified as [GHSA-965h-392x-2mh5](https://github.com/rustls/webpki/security/advisories/GHSA-965h-392x-2mh5). Thank you to @1seal for the report.
    ├ Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   └── libdd-trace-stats v5.0.0
      │   │       │   ├── libdd-trace-stats v5.0.0 (*)
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       ├── libdd-shared-runtime v1.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:220:1
    │
220 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0099
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0099
    ├ Permitted subtree name constraints for DNS names were accepted for certificates asserting a wildcard name.
      
      This was incorrect because, given a name constraint of `accept.example.com`, `*.example.com` could feasibly allow a name of `reject.example.com` which is outside the constraint.
      This is very similar to [CVE-2025-61727](https://go.dev/issue/76442).
      
      Since name constraints are restrictions on otherwise properly-issued certificates, this bug is reachable only after signature verification and requires misissuance to exploit.
      
      This vulnerability is identified as [GHSA-xgp8-3hg3-c2mh](https://github.com/rustls/webpki/security/advisories/GHSA-xgp8-3hg3-c2mh). Thank you to @1seal for the report.
    ├ Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   └── libdd-trace-stats v5.0.0
      │   │       │   ├── libdd-trace-stats v5.0.0 (*)
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       ├── libdd-shared-runtime v1.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:220:1
    │
220 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0104
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0104
    ├ A panic was reachable when parsing certificate revocation lists via [`BorrowedCertRevocationList::from_der`]
      or [`OwnedCertRevocationList::from_der`].  This was the result of mishandling a syntactically valid empty
      `BIT STRING` appearing in the `onlySomeReasons` element of a `IssuingDistributionPoint` CRL extension.
      
      This panic is reachable prior to a CRL's signature being verified.
      
      Applications that do not use CRLs are not affected.
      
      Thank you to @tynus3 for the report.
    ├ Solution: Upgrade to >=0.103.13, <0.104.0-alpha.1 OR >=0.104.0-alpha.7 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   └── libdd-trace-stats v5.0.0
      │   │       │   ├── libdd-trace-stats v5.0.0 (*)
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       ├── libdd-trace-obfuscation v4.0.0
      │   │       │       │   └── libdd-trace-stats v5.0.0 (*)
      │   │       │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       ├── libdd-shared-runtime v1.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v4.0.0 (*)
      │   │       ├── libdd-trace-stats v5.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

advisories FAILED, bans ok, sources ok

📦 libdd-trace-utils - 4 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:181:1
    │
181 │ rand 0.8.5 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ unsound advisory detected
    │
    ├ ID: RUSTSEC-2026-0097
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0097
    ├ It has been reported (by @lopopolo) that the `rand` library is [unsound](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) (i.e. that safe code using the public API can cause Undefined Behaviour) when all the following conditions are met:
      
      - The `log` and `thread_rng` features are enabled
      - A [custom logger](https://docs.rs/log/latest/log/#implementing-a-logger) is defined
      - The custom logger accesses `rand::rng()` (previously `rand::thread_rng()`) and calls any `TryRng` (previously `RngCore`) methods on `ThreadRng`
      - The `ThreadRng` (attempts to) reseed while called from the custom logger (this happens every 64 kB of generated data)
      - Trace-level logging is enabled or warn-level logging is enabled and the random source (the `getrandom` crate) is unable to provide a new seed
      
      `TryRng` (previously `RngCore`) methods for `ThreadRng` use `unsafe` code to cast `*mut BlockRng<ReseedingCore>` to `&mut BlockRng<ReseedingCore>`. When all the above conditions are met this results in an aliased mutable reference, violating the Stacked Borrows rules. Miri is able to detect this violation in sample code. Since construction of [aliased mutable references is Undefined Behaviour](https://doc.rust-lang.org/stable/nomicon/references.html), the behaviour of optimized builds is hard to predict.
    ├ Announcement: https://github.com/rust-random/rand/pull/1763
    ├ Solution: Upgrade to >=0.10.1 OR <0.10.0, >=0.9.3 OR <0.9.0, >=0.8.6 (try `cargo update -p rand`)
    ├ rand v0.8.5
      ├── (dev) libdd-common v4.2.0
      │   ├── libdd-capabilities-impl v2.0.0
      │   │   └── libdd-trace-utils v8.0.0
      │   │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   └── libdd-trace-utils v8.0.0 (*)
      ├── (dev) libdd-trace-normalization v2.0.0
      │   └── libdd-trace-utils v8.0.0 (*)
      ├── libdd-trace-utils v8.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v8.0.0 (*)

error[vulnerability]: Name constraints for URI names were incorrectly accepted
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:206:1
    │
206 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0098
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0098
    ├ Name constraints for URI names were ignored and therefore accepted.
      
      Note this library does not provide an API for asserting URI names, and URI name constraints are otherwise not implemented.  URI name constraints are now rejected unconditionally.
      
      Since name constraints are restrictions on otherwise properly-issued certificates, this bug is reachable only after signature verification and requires misissuance to exploit.
      
      This vulnerability is identified as [GHSA-965h-392x-2mh5](https://github.com/rustls/webpki/security/advisories/GHSA-965h-392x-2mh5). Thank you to @1seal for the report.
    ├ Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:206:1
    │
206 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0099
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0099
    ├ Permitted subtree name constraints for DNS names were accepted for certificates asserting a wildcard name.
      
      This was incorrect because, given a name constraint of `accept.example.com`, `*.example.com` could feasibly allow a name of `reject.example.com` which is outside the constraint.
      This is very similar to [CVE-2025-61727](https://go.dev/issue/76442).
      
      Since name constraints are restrictions on otherwise properly-issued certificates, this bug is reachable only after signature verification and requires misissuance to exploit.
      
      This vulnerability is identified as [GHSA-xgp8-3hg3-c2mh](https://github.com/rustls/webpki/security/advisories/GHSA-xgp8-3hg3-c2mh). Thank you to @1seal for the report.
    ├ Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:206:1
    │
206 │ rustls-webpki 0.103.10 registry+https://github.com/rust-lang/crates.io-index
    │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
    │
    ├ ID: RUSTSEC-2026-0104
    ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0104
    ├ A panic was reachable when parsing certificate revocation lists via [`BorrowedCertRevocationList::from_der`]
      or [`OwnedCertRevocationList::from_der`].  This was the result of mishandling a syntactically valid empty
      `BIT STRING` appearing in the `onlySomeReasons` element of a `IssuingDistributionPoint` CRL extension.
      
      This panic is reachable prior to a CRL's signature being verified.
      
      Applications that do not use CRLs are not affected.
      
      Thank you to @tynus3 for the report.
    ├ Solution: Upgrade to >=0.103.13, <0.104.0-alpha.1 OR >=0.104.0-alpha.7 (try `cargo update -p rustls-webpki`)
    ├ rustls-webpki v0.103.10
      ├── rustls v0.23.37
      │   ├── hyper-rustls v0.27.7
      │   │   └── libdd-common v4.2.0
      │   │       ├── libdd-capabilities-impl v2.0.0
      │   │       │   └── libdd-trace-utils v8.0.0
      │   │       │       └── (dev) libdd-trace-utils v8.0.0 (*)
      │   │       └── libdd-trace-utils v8.0.0 (*)
      │   ├── libdd-common v4.2.0 (*)
      │   ├── rustls-platform-verifier v0.6.2
      │   │   └── libdd-common v4.2.0 (*)
      │   └── tokio-rustls v0.26.0
      │       ├── hyper-rustls v0.27.7 (*)
      │       └── libdd-common v4.2.0 (*)
      └── rustls-platform-verifier v0.6.2 (*)

advisories FAILED, bans ok, sources ok

Updated: 2026-06-18 19:18:00 UTC | Commit: 27b08f6 | dependency-check job results

@codecov-commenter

codecov-commenter commented Jun 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 78.94737% with 132 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.46%. Comparing base (a1da9fc) to head (cac8c75).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2067      +/-   ##
==========================================
+ Coverage   73.42%   73.46%   +0.04%     
==========================================
  Files         465      466       +1     
  Lines       77949    78552     +603     
==========================================
+ Hits        57231    57706     +475     
- Misses      20718    20846     +128     
Components Coverage Δ
libdd-crashtracker 65.46% <ø> (-0.02%) ⬇️
libdd-crashtracker-ffi 37.68% <ø> (ø)
libdd-alloc 98.77% <ø> (ø)
libdd-data-pipeline 86.33% <77.75%> (-0.80%) ⬇️
libdd-data-pipeline-ffi 77.03% <ø> (ø)
libdd-common 79.89% <ø> (ø)
libdd-common-ffi 74.41% <ø> (ø)
libdd-telemetry 73.34% <ø> (-0.03%) ⬇️
libdd-telemetry-ffi 31.36% <ø> (ø)
libdd-dogstatsd-client 82.64% <ø> (ø)
datadog-ipc 76.22% <ø> (ø)
libdd-profiling 81.69% <ø> (ø)
libdd-profiling-ffi 64.79% <ø> (ø)
libdd-sampling 97.41% <ø> (ø)
datadog-sidecar 34.59% <ø> (-0.02%) ⬇️
datdog-sidecar-ffi 8.61% <ø> (ø)
spawn-worker 48.86% <ø> (ø)
libdd-tinybytes 93.80% <ø> (ø)
libdd-trace-normalization 81.71% <ø> (ø)
libdd-trace-obfuscation 87.30% <ø> (ø)
libdd-trace-protobuf 68.25% <ø> (ø)
libdd-trace-utils 89.21% <ø> (ø)
libdd-tracer-flare 86.88% <ø> (ø)
libdd-log 74.83% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dd-octo-sts

dd-octo-sts Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.76 MB 7.76 MB +0% (+48 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 84.02 MB 84.55 MB +.63% (+548.25 KB) 🔍
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 95.13 MB 95.70 MB +.60% (+590.92 KB) 🔍
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.36 MB 10.44 MB +.74% (+79.29 KB) 🔍
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 24.93 MB 25.11 MB +.73% (+186.50 KB) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 181.51 MB 182.37 MB +.47% (+888.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 928.21 MB 932.36 MB +.44% (+4.14 MB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.12 MB 8.22 MB +1.26% (+105.00 KB) ⚠️
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.33 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 24.03 MB 24.20 MB +.71% (+176.00 KB) 🔍
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 47.96 MB 48.33 MB +.76% (+375.97 KB) 🔍
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 21.62 MB 21.78 MB +.74% (+166.00 KB) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 88.71 KB 88.71 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 185.58 MB 186.48 MB +.48% (+928.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 921.15 MB 925.39 MB +.45% (+4.23 MB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.27 MB 6.33 MB +.98% (+63.50 KB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 88.71 KB 88.71 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 25.76 MB 25.96 MB +.75% (+200.00 KB) 🔍
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 45.59 MB 45.94 MB +.75% (+354.10 KB) 🔍
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 74.91 MB 75.37 MB +.61% (+473.75 KB) 🔍
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.61 MB 8.68 MB +.72% (+64.03 KB) 🔍
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 90.33 MB 90.83 MB +.55% (+508.98 KB) 🔍
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.48 MB 10.56 MB +.69% (+74.78 KB) 🔍

@mabdinur mabdinur force-pushed the munir/otlp-trace-metrics branch from ad8610e to dbc8c4b Compare June 15, 2026 19:46
@mabdinur mabdinur changed the title feat(data-pipeline): export client-computed span stats as OTLP trace metrics feat(data-pipeline)!: export client-computed span stats as OTLP trace metrics Jun 15, 2026
@mabdinur mabdinur force-pushed the munir/otlp-trace-metrics branch from dbc8c4b to 43fdf9b Compare June 15, 2026 20:01
mabdinur and others added 5 commits June 15, 2026 16:46
Foundation pieces consumed by the OTLP trace-metrics exporter that follows.
These are pure additions with no breaking changes.

- libdd-ddsketch: `DDSketch::from_pb` rebuilds a sketch from its protobuf
  representation (or `None` when the mapping is missing/invalid); a thin
  `DDSketch::from_encoded` wraps protobuf decoding + `from_pb`. Lets callers
  read back the ok/error sketches that the span concentrator publishes.
  Includes a roundtrip test that goes `encode_to_vec` -> `from_encoded` and
  asserts bin count + total weight survive the trip.

- libdd-trace-utils: extend `OtlpResourceInfo` with two new fields:
  `hostname` (emitted as the `host.name` resource attribute when set) and
  `process_tags` (comma-separated `key:value` pairs, each becoming a
  `dd.<key>` resource attribute). The struct is `#[non_exhaustive]`, so
  adding fields is forward-compatible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Make the span concentrator accumulate exact per-cell (ok/error) duration
totals and min/max in nanoseconds alongside the existing combined `duration`
that the /v0.6/stats agent payload uses, and publish them on a new sidecar
that the OTLP trace-metrics path can read.

- `GroupedStats` gains six pub(super) accumulators (`ok_duration`/`ok_min`/
  `ok_max` + the error trio) updated inside `insert`. They are seeded on the
  first span in each cell (count == 1) so the natural `0` default cannot
  masquerade as a real minimum.

- New public types `OtlpExactCell`, `OtlpExactGroup`, `OtlpStatsBucket` carry
  the exact scalars alongside an unmodified `pb::ClientStatsBucket`. The
  `grpc_method` field on `OtlpExactGroup` is intentionally introduced here
  but only ever populated with `String::new()`; a later commit fills it in.

- `StatsBucket::flush` now delegates to a new `flush_with_otlp_exact` which
  produces both the protobuf bucket (identical bytes) and the parallel
  sidecar. `SpanConcentrator::flush` and `flush_with_otlp_exact` share a
  generic `drain_due_buckets` helper so the bucket-window/buffer-len logic
  stays in one place.

- A new concentrator test drives the full path through `add_span` for 3 ok
  + 2 error spans and asserts each cell's count/duration/min/max plus
  `ok_duration + error_duration == group.duration` (the agent field).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nfig

Prepare the data-pipeline OTLP layer to host a second exporter (trace
metrics) without changing the existing trace path's behavior or public API.

- `otlp/exporter.rs`: factor the actual POST + retry plumbing into a new
  crate-private `send_otlp_http(endpoint_url, headers, timeout, ...)` helper.
  `send_otlp_traces_http` becomes a thin wrapper that pulls fields out of
  `OtlpTraceConfig` and calls it; the existing public function signature is
  unchanged, so external callers see no diff. Two new pub(crate) constants
  (`OTLP_MAX_ATTEMPTS`, `OTLP_SHUTDOWN_MAX_ATTEMPTS`) replace the previous
  `OTLP_MAX_RETRIES` literal so the trace-metrics worker can use a single
  attempt on shutdown.

- `otlp/config.rs`: add `OtlpMetricsConfig` mirroring `OtlpTraceConfig`
  plus an `otel_trace_semantics_enabled` flag for `DD_TRACE_OTEL_SEMANTICS_ENABLED`.
  Annotated `#[allow(dead_code)]` until a follow-up commit consumes it.

- `trace_exporter/builder.rs`: factor the inline OTLP header-map builder
  out of `build_async` into a small `build_otlp_header_map` helper and
  refactor the existing OTLP traces config building to use it. No behavior
  change; this dedup makes the metrics-config branch trivial when it lands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…metrics

Wire up the actual OTLP trace-metrics exporter on top of the foundation
pieces from earlier commits.

- New `libdd-data-pipeline/src/otlp/metrics.rs`:
  - `map_stats_to_otlp_metrics` builds an `ExportMetricsServiceRequest`
    JSON value from `&[OtlpStatsBucket]` (one histogram data point per
    aggregation-key (ok|error) cell). `count`/`sum`/`min`/`max` come from
    the sidecar's exact accumulators (ns -> s); `bucketCounts` is projected
    from the per-cell DDSketch onto a fixed 17-bucket spanmetrics-style
    layout. Empty cells are suppressed.
  - `OtlpStatsExporter<C>` runs as a `libdd_shared_runtime::Worker`:
    `trigger` waits one flush interval, `run` flushes + sends with
    `OTLP_MAX_ATTEMPTS`, `shutdown` force-flushes with
    `OTLP_SHUTDOWN_MAX_ATTEMPTS` (single attempt) so the final bucket is
    delivered inside the bounded shutdown window.
  - The mapper consumes `exact.grpc_method` (always empty here) so the
    later breaking-change commit only has to fill it in.

- `otlp/mod.rs`: declare the new `metrics` module, re-export
  `OtlpMetricsConfig` and `OtlpStatsExporter`, and extend the module-level
  doc to describe the trace-metrics path.

- `trace_exporter/builder.rs`: add `otlp_metrics_endpoint`,
  `otlp_metrics_headers` and `otel_trace_semantics_enabled` fields with
  matching setters (`set_otlp_metrics_endpoint`, `set_otlp_metrics_headers`,
  `enable_otel_trace_semantics`). When both an OTLP metrics endpoint and a
  stats bucket size are configured, spawn an `OtlpStatsExporter` worker on
  the shared runtime against an unconditionally-started
  `SpanConcentrator`; set a new `otlp_stats_enabled` flag on `TraceExporter`
  so the agent-info gate cannot later disable stats. The agent /v0.6/stats
  payload bytes are unchanged when no OTLP metrics endpoint is set.

- `trace_exporter/mod.rs`: add the `otlp_stats_enabled` field on
  `TraceExporter`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add the gRPC method name to the aggregation key so spans sharing the same
service/resource/etc. but different `grpc.method.name` aggregate into
distinct groups, and surface the value via the OTLP trace-metrics sidecar
introduced earlier on this branch.

- `aggregation.rs`:
  - New `GRPC_METHOD_FIELD` lookup list (`grpc.method.name`, fallback
    `rpc.method`) consumed by a new `get_grpc_method` helper.
  - New `FixedAggregationKey<T>.grpc_method` field, appended at the END of
    the struct so the `PartialOrd` derive's field order (and therefore the
    ordering of any existing comparisons) is unaffected for the pre-existing
    fields.
  - `BorrowedAggregationKey::from_obfuscated_span` now picks up
    `grpc_method`; `OwnedAggregationKey::From<pb::ClientGroupedStats>` sets
    it to `""` (the agent stats protobuf does not carry it).
  - `StatsBucket::flush_with_otlp_exact` does `std::mem::take` on the key's
    `grpc_method` and moves it into `OtlpExactGroup.grpc_method` before
    encoding the agent payload, so the OTLP path reads it from the sidecar
    while the /v0.6/stats wire format stays byte-for-byte unchanged.
  - Aggregation test gains a case asserting that `grpc.method.name` (and
    by fallthrough, `rpc.method`) are extracted into the key.

- `datadog-ipc/src/shm_stats.rs`: the SHM concentrator's
  `FixedAggregationKey` test fixture grows a `grpc_method: ""` field.

BREAKING CHANGE: `FixedAggregationKey<T>` (re-exported from
`libdd_trace_stats::span_concentrator`) gains a public `grpc_method: T`
field. External callers that construct it via a struct literal must add
the field; callers using `Default::default()` are unaffected. The /v0.6/stats
agent protobuf wire format and behavior are unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@mabdinur mabdinur force-pushed the munir/otlp-trace-metrics branch from 43fdf9b to f330f8b Compare June 15, 2026 20:47
@mabdinur mabdinur marked this pull request as ready for review June 15, 2026 22:54
@mabdinur mabdinur requested review from a team as code owners June 15, 2026 22:55
@mabdinur mabdinur requested review from vpellan and removed request for a team June 15, 2026 22:55

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f330f8bee6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread libdd-trace-stats/src/span_concentrator/aggregation.rs Outdated
Comment thread libdd-data-pipeline/src/trace_exporter/mod.rs Outdated
mabdinur and others added 3 commits June 15, 2026 19:49
…n SDK computes stats

When otlp_stats_enabled, add _dd.stats_computed="true" to the OTLP ResourceSpans resource
attributes and Datadog-Client-Computed-Stats: yes to the HTTP request headers. The Agent's
OTLP receiver already checks both signals (otlp.go:372, otlp.go:272) and skips its
concentrator when either is set, preventing double-counted APM metrics.

The resource attribute survives Collector hops (unlike HTTP headers); the header covers direct
SDK→Agent connections. Both are backwards compatible: older Agents and non-Datadog OTLP
receivers silently ignore unknown resource attributes and headers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… negotiation with OTLP stats

grpc_method was part of FixedAggregationKey (Hash+PartialEq), splitting same-service gRPC spans
into separate buckets that encode_grouped_stats then serialised with an empty method — producing
duplicate indistinguishable ClientGroupedStats rows on the /v0.6/stats path. Move it to
GroupedStats (value side), set on group creation, and surface it to OtlpExactGroup from there.
This also removes the one breaking change introduced by the prior commit.

check_agent_info returned before refresh_v1_active when otlp_stats_enabled, preventing V1
protocol negotiation for exporters that combine enable_v1_protocol with OTLP metrics. Move the
early return to after the V1 refresh so only stats enable/disable is skipped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… negotiation with OTLP stats

grpc_method was part of FixedAggregationKey (Hash+PartialEq), splitting same-service gRPC spans
into separate buckets that encode_grouped_stats then serialised with an empty method — producing
duplicate indistinguishable ClientGroupedStats rows on the /v0.6/stats path. Move it to
GroupedStats (value side), set on group creation, and surface it to OtlpExactGroup from there.
This also removes the one breaking change introduced by the prior commit.

check_agent_info returned before refresh_v1_active when otlp_stats_enabled, preventing V1
protocol negotiation for exporters that combine enable_v1_protocol with OTLP metrics. Move the
early return to after the V1 refresh so only stats enable/disable is skipped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@gh-worker-ownership-write-b05516 gh-worker-ownership-write-b05516 Bot removed the request for review from a team June 16, 2026 00:47
@mabdinur mabdinur requested a review from rachelyangdog June 16, 2026 13:50
Comment thread libdd-trace-utils/src/otlp_encoder/mapper.rs
const OTLP_MAX_RETRIES: u32 = 4;
/// Initial backoff between retries (milliseconds).
/// Max total attempts for OTLP export (initial + retries on transient failures).
pub(crate) const OTLP_MAX_ATTEMPTS: u32 = 5;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Any reason to use attempts instead of retry. I'm trying to converge to using retries as mixing the two can cause bugs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair nit — happy to rename back to retries for consistency. The rename to attempts was to make the semantics clearer (OTLP_SHUTDOWN_MAX_ATTEMPTS = 1 means one try, no retries), but retries is fine too if that's the established convention.

Comment thread libdd-trace-stats/src/span_concentrator/aggregation.rs
Comment thread libdd-data-pipeline/src/trace_exporter/builder.rs Outdated
Comment thread libdd-data-pipeline/src/trace_exporter/mod.rs

@ichinaski ichinaski left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from the Data Pipeline point of view

- Rename OTLP_MAX_ATTEMPTS/OTLP_SHUTDOWN_MAX_ATTEMPTS to OTLP_MAX_RETRIES/
  OTLP_SHUTDOWN_MAX_RETRIES and rename the max_attempts parameter to
  max_retries throughout, converging on the retries convention used elsewhere
- Add TraceExporterBuilder::set_runtime_id so callers can supply the language
  tracer's existing runtime_id; falls back to a generated UUID when not set,
  ensuring OTLP trace exports and OTLP trace-metrics share the same runtime_id
  for backend correlation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

4 participants