Skip to content

feat(data-pipeline): OTLP HTTP/protobuf trace export#2115

Open
bm1549 wants to merge 33 commits into
mainfrom
brian.marks/otlp-http-protobuf-export
Open

feat(data-pipeline): OTLP HTTP/protobuf trace export#2115
bm1549 wants to merge 33 commits into
mainfrom
brian.marks/otlp-http-protobuf-export

Conversation

@bm1549

@bm1549 bm1549 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds OTLP HTTP/protobuf as a trace-export encoding alongside HTTP/JSON, selectable via the OTel-standard OTEL_EXPORTER_OTLP_TRACES_PROTOCOL (http/json default, http/protobuf). The generated prost OTLP types are the single intermediate representation: the mapper builds them directly from native spans, protobuf is prost::encode_to_vec, and JSON is a serde serializer over the same types. grpc parses but is rejected (HTTP-only).

Motivation

libdatadog's OTLP trace export only spoke HTTP/JSON. SDKs that honor OTEL_EXPORTER_OTLP_TRACES_PROTOCOL need http/protobuf to match the OTel default and to talk to collectors that expect protobuf.

Additional Notes

  • Prost is the single IR: no parallel hand-rolled JSON model, no string round-trip. The mapper maps native spans straight to prost; encode_otlp_protobuf is encode_to_vec; encode_otlp_json is a serde serializer (json_serializer.rs) emitting OTLP-spec JSON (hex ids, base64 bytes, int64-as-string, lowerCamelCase, proto3 defaults omitted).
  • Protocol handling: the user-facing OtlpProtocol carries Grpc; an internal OtlpWireProtocol { Json, Protobuf } encapsulates content_type()/encode(). gRPC is rejected, but only when an OTLP endpoint is configured, so a grpc value left over from OTEL_EXPORTER_OTLP_PROTOCOL stays inert for a normal agent exporter.
  • Vendors the OTLP trace/collector protos; their doc comments are kept (one example block is fenced as text so rustdoc doesn't run it as a doctest).
  • Benchmarks for the encoder hot paths, plus allocation-informed tuning (pre-sized Vecs, allocation-free id/timestamp/int serialization).

How to test the change?

  • cargo test -p libdd-trace-utils -p libdd-data-pipeline -p libdd-data-pipeline-ffi, cargo test --doc, clippy, fmt, and cargo ffi-test pass. A parity test asserts the JSON and protobuf encodings carry the same span from the one prost IR.
  • End-to-end through dd-trace-py (feat(otlp): support http/protobuf OTLP trace export dd-trace-py#18609): emitted protobuf-only OTLP traces through a local Agent to the backend. Wire was application/x-protobuf (HTTP 200), spans ingested with correct service/resource and a preserved 128-bit trace id.
  • Benchmarks: cargo bench -p libdd-trace-utils --bench main -- otlp/.

BREAKING CHANGE: removes the previously public libdd_trace_utils::otlp_encoder::json_types module (the hand-rolled OTLP JSON model: OtlpSpan, ExportTraceServiceRequest, KeyValue, Status, the span_kind/status_code consts, etc.). OTLP encoding now builds prost-generated types as the single IR. libdatadog consumers pin by version, so they pick this up on the next release.

bm1549 and others added 15 commits June 12, 2026 14:09
Records the approved design: vendor OTLP trace + collector protos and
generate prost types (zero new runtime deps), keep the hand-rolled serde
JSON path, share one mapper with a serde->prost converter, and select the
protocol via builder + C FFI. Includes the dd-trace-py companion wiring
and the layered E2E plan (local receiver, system-tests, sdk-backend-verify).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bite-sized, TDD-structured plan across 9 phases: vendor+generate prost
types, serde->prost converter, encoder dispatch, protocol config through
builder + C FFI, full validation gauntlet + libdatadog PR, then dd-trace-py
PyO3/writer wiring and three E2E tiers (local receiver, system-tests,
sdk-backend-verify) + dd-trace-py PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vendors opentelemetry/proto/trace/v1/trace.proto and
opentelemetry/proto/collector/trace/v1/trace_service.proto from
open-telemetry/opentelemetry-proto commit 1e725b853bc8f6b46ee62e8232e4c83017b9536f
(matching the already-vendored common.proto and resource.proto).

Adds both protos to the prost_build compile list in build.rs, generates
the committed Rust types (opentelemetry.proto.trace.v1.rs and
opentelemetry.proto.collector.trace.v1.rs), and updates _includes.rs.

Also qualifies "Span" → "pb.Span" / "pb.idx.Span" in build.rs
type_attribute calls to prevent serde derives from leaking into the
new opentelemetry::proto::trace::v1::Span type.
…ests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-type match

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bm1549 bm1549 added the AI Generated PR largely written by AI tools label Jun 12, 2026
@datadog-datadog-prod-us1

datadog-datadog-prod-us1 Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 2 Pipeline jobs failed

Miri test | run-miri (3)   View in Datadog   GitHub Actions

Required checks pass | allchecks   View in Datadog   GitHub Actions

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 81.36%
Overall Coverage: 73.86% (+0.82%)

Useful? React with 👍 / 👎

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

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 3025 documentation warning(s) found

📦 libdd-data-pipeline-ffi - 1197 warning(s)

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

📦 libdd-trace-protobuf - 121 warning(s)

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


Updated: 2026-06-19 02:16:02 UTC | Commit: 9b98898 | missing-docs job results

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Clippy Allow Annotation Report

Comparing clippy allow annotations between branches:

  • Base Branch: origin/main
  • PR Branch: origin/brian.marks/otlp-http-protobuf-export

Summary by Rule

Rule Base Branch PR Branch Change
unwrap_used 2 2 No change (0%)
Total 2 2 No change (0%)

Annotation Counts by File

File Base Branch PR Branch Change
libdd-data-pipeline/src/trace_exporter/mod.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 5 No change (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 181 No change (0%)

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.

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

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

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

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:226:1
    │
226 │ 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-data-pipeline-ffi v35.0.0
      │   │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
      │   │   ├── libdd-shared-runtime v1.0.0
      │   │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │   │   ├── libdd-data-pipeline-ffi v35.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 (*)
      │   │       ├── (dev) libdd-data-pipeline-ffi v35.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-common-ffi v35.0.0
      │   │   └── libdd-data-pipeline-ffi v35.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 (*)
              ├── libdd-data-pipeline-ffi v35.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:253:1
    │
253 │ 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-data-pipeline-ffi v35.0.0
      │   │       │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   ├── libdd-data-pipeline-ffi v35.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 (*)
      │   │       │       ├── (dev) libdd-data-pipeline-ffi v35.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-common-ffi v35.0.0
      │   │       │   └── libdd-data-pipeline-ffi v35.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:253:1
    │
253 │ 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-data-pipeline-ffi v35.0.0
      │   │       │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   ├── libdd-data-pipeline-ffi v35.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 (*)
      │   │       │       ├── (dev) libdd-data-pipeline-ffi v35.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-common-ffi v35.0.0
      │   │       │   └── libdd-data-pipeline-ffi v35.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:253:1
    │
253 │ 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-data-pipeline-ffi v35.0.0
      │   │       │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
      │   │       │   ├── libdd-shared-runtime v1.0.0
      │   │       │   │   ├── libdd-data-pipeline v6.0.0 (*)
      │   │       │   │   ├── libdd-data-pipeline-ffi v35.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 (*)
      │   │       │       ├── (dev) libdd-data-pipeline-ffi v35.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-common-ffi v35.0.0
      │   │       │   └── libdd-data-pipeline-ffi v35.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:295:1
    │
295 │ 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
                  └── libdd-data-pipeline-ffi v35.0.0

advisories FAILED, bans ok, sources ok

📦 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-trace-protobuf - ✅ No issues

📦 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-19 02:17:36 UTC | Commit: 9b98898 | dependency-check job results

@bm1549 bm1549 force-pushed the brian.marks/otlp-http-protobuf-export branch from ee71538 to 664f16f Compare June 12, 2026 19:51
@dd-octo-sts

dd-octo-sts Bot commented Jun 12, 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.a 83.68 MB 83.93 MB +.29% (+254.93 KB) 🔍
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.70 MB 7.70 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 94.78 MB 95.03 MB +.25% (+250.39 KB) 🔍
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.34 MB 10.35 MB +.05% (+5.77 KB) 🔍
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 24.83 MB 24.88 MB +.20% (+52.00 KB) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.68 KB +.40% (+360 B) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 180.85 MB 181.64 MB +.43% (+808.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 925.13 MB 927.69 MB +.27% (+2.55 MB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.09 MB 8.09 MB +.08% (+7.00 KB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 87.33 KB 87.68 KB +.40% (+360 B) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 23.94 MB 24.01 MB +.32% (+80.00 KB) 🔍
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 47.78 MB 47.89 MB +.22% (+108.99 KB) 🔍
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 21.52 MB 21.56 MB +.21% (+47.00 KB) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 88.71 KB 89.06 KB +.40% (+364 B) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 184.87 MB 185.69 MB +.44% (+848.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 918.09 MB 920.72 MB +.28% (+2.63 MB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.24 MB 6.25 MB +.11% (+7.50 KB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 88.71 KB 89.06 KB +.40% (+364 B) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 25.66 MB 25.75 MB +.36% (+96.00 KB) 🔍
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 45.41 MB 45.52 MB +.24% (+114.74 KB) 🔍
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 74.60 MB 74.82 MB +.30% (+230.79 KB) 🔍
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.58 MB 8.59 MB +.09% (+8.00 KB) 🔍
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 90.02 MB 90.24 MB +.24% (+227.90 KB) 🔍
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.44 MB 10.45 MB +.11% (+11.82 KB) 🔍

The OTLP design spec and implementation plan are linked from the PR
description (internal chonk) rather than committed to the repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bm1549 bm1549 marked this pull request as ready for review June 12, 2026 21:37
@bm1549 bm1549 requested review from a team as code owners June 12, 2026 21:37
@bm1549 bm1549 requested a review from a team as a code owner June 12, 2026 21:37
@bm1549 bm1549 requested review from mabdinur and removed request for a team June 12, 2026 21:37
Selecting OtlpProtocol::Grpc on the Rust builder previously built a
working-looking exporter that then failed on every send with a
mis-typed Internal(InvalidWorkerState) error. Reject it in build_async
(covering sync build + wasm) with BuilderErrorKind::InvalidConfiguration
(FFI: InvalidArgument), matching the C FFI set_otlp_protocol setter so
both entry points fail fast and identically. The send-time arm stays as
a defensive guard.

Also replace the "skip as instructed" placeholder comment in the OTLP
serde->prost converter with a real test exercising link()/event()
conversion (link trace/span ID byte assembly, tracestate, and
link/event attributes).

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

@mabdinur mabdinur left a comment

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.

Faithful protobuf encoder with safe fallbacks (no panics), correct content-type selection, and gRPC is rejected at both build and send time. No breaking API changes and good JSON/protobuf parity tests. LGTM.

@mabdinur mabdinur left a comment

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.

Approval stands, these are all nits / follow-up material, nothing blocking:

  1. proto_convert.rs (perf): on the http/protobuf path, mapper.rs formats every ID to a hex string and every timestamp to a string, then this code reverses it (hex_to_bytes/parse_u64) and deep-clones the whole serde tree, per span per export. Native IDs are u128/u64 already. Reasonable as a documented v1, but worth a follow-up to build the prost types straight from the native span types and skip the round-trip.

  2. otlp/config.rs: OtlpProtocol is public but not #[non_exhaustive]. Nothing breaks today since it's new, but without it any future variant becomes a breaking change for downstream exhaustive matches. Worth adding now while the enum is fresh.

  3. otlp_encoder/mod.rs (scope question): confirming this is traces-only, which seems like the right first step with OtlpProtocol as the encoding axis. Are metrics/logs intentionally out of scope here, handled by separate signal pipelines rather than extending this path?

  4. json_types.rs (maintainability): the OTLP schema now has two hand-maintained representations (serde json_types and prost) bridged by the From impls in proto_convert, with no shared source of truth, so a field added to one side can silently diverge. The cross-encoder parity test only compares name and spanId. Could we extend it to trace_id (base64 vs raw bytes), status, and at least one attribute so drift gets caught?

  5. libdd-data-pipeline-ffi/src/trace_exporter.rs: the protocol string re-parse can't fail today since the setter already restricts the values, so an error here is a silent no-op. If the accepted set ever drifts from FromStr this would quietly drop the protocol. Consider expect/log, or rely on the builder validation.

// Copyright 2024-Present Datadog, Inc. https://www.datadoghq.com/
// SPDX-License-Identifier: Apache-2.0

//! Converts the hand-rolled serde OTLP request (the JSON wire model) into the generated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is going to be incredibly unperformant. The mapper is taking a Span and turning everything into a String for JSON. And then this is converting everything back for protobuf, which is also doing unnecessary extra string allocations.

The problem is the mapper is conflating mapping to OTLP and serializing the wire format. I think it would be much better to refactor the mapper to use an intermediate representation and separate concerns. Using prost for the IR probably makes the most sense? It'll be much more performant to build prost types in the mapper, then serialize them directly to JSON via Serde.

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.

This to me is the fundamental problem. It re-introduces the same problems I just spent 9 months trying to fix.

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.

Good call, thanks for pushing on this. Reworked it so prost is the single IR - the mapper builds prost types directly from native spans, then protobuf is encode_to_vec and JSON serializes the same types via serde. No more String round-trip. Updated in b21be02. @bengl should cover your concern too.

}
}

impl From<&j::ExportTraceServiceRequest> for ProtoReq {

@ekump ekump Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

From taking the request by ref, with only a borrow you can't move the owned Strings out is leading to a ton of clones in proto_convert. Where this is used the serde request is a single-use intermediate that quickly gets dropped after. If you change this to From<ExportTraceServiceRequest> you can avoid a lot of costly allocations.

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.

Updated in 55541eb

crate::otlp::config::OtlpProtocol::HttpProtobuf => {
libdd_common::header::APPLICATION_PROTOBUF
}
crate::otlp::config::OtlpProtocol::HttpJson | crate::otlp::config::OtlpProtocol::Grpc => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wouldn't recommended silently setting the content_type to JSON here when matching on GRPC. Just return an error. The function signature is already a Result.

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.

Updated in 809914e

#[allow(dead_code)]
pub(crate) protocol: OtlpProtocol,
/// OTLP export protocol (selects body encoding and content-type).
pub protocol: OtlpProtocol,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We're matching protocol several times in this PR and it's kind of awkward because OtlpProtocol contains a currently unsupported variant. Why not keep the user facing OtlpProtocol as is, and internally have something like enum OtlpWireProtocol { Json, Protobuf }? It'll make the code much cleaner and when GRPC support is added you can get rid of OTLPWireProtocol. Or you could do:

  impl OtlpWireProtocol {                                                                                                                                                                                                                                                               
      fn content_type(&self) -> HeaderValue { /* 2 arms */ }                                                                                                                                                                                                                            
      fn encode(&self, req: &ExportTraceServiceRequest) -> Result<Vec<u8>> { /* 2 arms */ }                                                                                                                                                                                             
  } 

and encapsulate the correct behavior in the type.

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.

Updated in 809914e

Comment thread libdd-trace-protobuf/build.rs Outdated

config.out_dir(output_path.clone());

// The vendored OpenTelemetry trace protos carry doc comments with indented example blocks

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This means no docs for the protobuf files will be generated at all. You can just update the Cargo.toml and add doctest = false to [lib] and get rid of this.

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.

Good call on keeping the docs. doctest = false on [lib] doesn't actually stop cargo test --doc from compiling the proto comments, so instead I dropped disable_comments, kept the docs, and fenced the one example as a text block so rustdoc renders it instead of running it. Updated in 18f28c5.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This doc needs to be updated

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.

Updated in a790182

)
}

/// Sets the OTLP export protocol. Accepts the OTel-standard values `http/json` (default) or

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The doc should probably make it clear that this function is inert if an otlp endpoint isn't set.

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.

Updated in a790182

if let Some(ref proto) = config.otlp_protocol {
// The FFI setter only stores "http/json"/"http/protobuf", so this parse always
// succeeds here; a parse failure just leaves the builder's default protocol.
if let Ok(p) = proto.parse::<libdd_data_pipeline::otlp::OtlpProtocol>() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Similar to other comments, this is dangerous if there is ever code drift. This silently drops a parse failure and falls back to the default protocol.

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.

Updated in 1cb1dfb

TraceExporterError::Internal(InternalErrorKind::InvalidWorkerState(e.to_string()))
})?,
OtlpProtocol::HttpProtobuf => {
libdd_trace_utils::otlp_encoder::encode_otlp_protobuf(&request)

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.

Where's the error handling here, like the with the other protocols?

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.

Added in 809914e - wire.encode() returns a Result now and the error is logged + propagated, same as the others.

use std::time::Duration;

/// OTLP trace export protocol. HTTP/JSON is currently supported.
/// OTLP trace export protocol.

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.

Seems like grpc should still be excluded here?

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.

Kept Grpc on the user-facing OtlpProtocol (#[non_exhaustive], room for later), but it's excluded from the wire path - OtlpWireProtocol is Json/Protobuf only, and grpc errors at build when an endpoint is set. 809914e / 855f4c1.

bm1549 and others added 13 commits June 18, 2026 16:46
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… encoding, errors on grpc

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The build-time gRPC check fired unconditionally, so a `grpc` protocol
(e.g. resolved from the OTel-default OTEL_EXPORTER_OTLP_PROTOCOL) failed
the build of a normal Datadog-agent exporter even with no OTLP endpoint
set — violating the "protocol is inert without an endpoint" contract.
Move the rejection inside the OTLP-endpoint branch so it only fires when
OTLP export is actually enabled. The send-time arm remains a guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…per-span alloc

Pre-push review cleanups: keep the internal OtlpWireProtocol and the
json_serializer module crate-private (not public API surface), and use
eq_ignore_ascii_case in the span-kind mappers to avoid a per-span
to_lowercase() allocation on the encode hot path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Criterion benches for the OTLP encoder hot paths — native spans -> prost
IR (the mapper), and prost IR -> HTTP/protobuf and HTTP/JSON wire — plus
end-to-end map+encode, over ~1000-span payloads (one large trace and many
small traces). Inputs are decoded from msgpack into borrowed SpanSlices,
matching the production exporter path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… hex

Pre-size the per-export span Vec and per-span attribute Vec in the prost
mapper to avoid reallocations as they fill. This also makes the resulting
prost IR more compact, speeding up the downstream protobuf encode (a
sequential read of the IR). Serialize OTLP/JSON trace/span ids from a
stack buffer (hex::encode_to_slice) instead of allocating a String per id.

Benches (~1000 spans): map -21%, protobuf encode -19%, JSON encode -9%,
end-to-end -10..12%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ck buffer

OTLP encodes 64-bit integers (nanosecond timestamps and intValue
attributes) as JSON strings to avoid precision loss; these were each
allocating a String per span via to_string(). Format them into a stack
buffer instead (NumStr, mirroring the HexId id writer). Removes ~3
timestamp + N int-attribute String allocations per span on the JSON path.

Bench: encode_json a further -4.5% (now -12.5% vs the original baseline).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s text

Addresses the build.rs comment-strip review note. `[lib] doctest = false`
does not suppress doctests under `cargo test --doc` (a required gate), so
instead fence the one offending example block (Span.attributes in
trace.proto) as a ```text block — rustdoc renders it as text, not a Rust
doctest — and drop `disable_comments` so the OTLP proto docs are generated
onto the prost structs again. `cargo test --doc` stays green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
test_otlp_grpc_without_endpoint_still_builds builds a real TraceExporter,
which spawns the agent_info worker and makes syscalls miri can't execute.
Add #[cfg_attr(miri, ignore)] to match the file's other live-build tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Generated PR largely written by AI tools data-pipeline mini-agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants