Skip to content

feat(data-pipeline)!: add stdout log trace exporter#2074

Open
bengl wants to merge 1 commit into
mainfrom
bengl/trace-log-exporter
Open

feat(data-pipeline)!: add stdout log trace exporter#2074
bengl wants to merge 1 commit into
mainfrom
bengl/trace-log-exporter

Conversation

@bengl

@bengl bengl commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds a stdout "log exporter" transport to libdatadog's trace pipeline. When enabled, TraceExporter writes traces as newline-delimited JSON ({"traces":[[...]]}) to stdout in the format consumed by the Datadog Forwarder, instead of sending them to an agent over HTTP.

New pieces:

  • libdd-trace-utils::json_log_encoder — Forwarder JSON encoder: lowercase hex IDs (incl. 128-bit), integer error, ns start/duration, empty-field omission, greedy 256 KiB line batching, oversize-span drop.
  • TraceExporterBuilder::set_output_to_log(max_line_size) — selects a stdout destination that bypasses agent-info polling, client-side stats, V1 negotiation, and telemetry. Exposed over FFI as ddog_trace_exporter_config_set_output_to_log.
  • libdd_capabilities::LogWriterCapability — the write goes through a capability so the transport also works on wasm (where the host, e.g. JavaScript, supplies the sink). The native capability writes to stdout.

Motivation

Serverless runtimes (primarily AWS Lambda) often have no reachable Datadog agent or Lambda extension. The established fallback is to write traces to stdout, where the Datadog Forwarder tails the logs and submits them to the trace intake. Today each tracer (dd-trace-js/py/go/java) reimplements this independently; this lands a single reusable implementation in libdatadog that native-backed tracers can adopt.

Additional Notes

  • Breaking (Rust API): TraceExporter<C> (and TraceExporterBuilder::build/build_async, trace_buffer::DefaultExport<C>) now require C: LogWriterCapability. Callers using a custom capability bundle must implement libdd_capabilities::LogWriterCapability; NativeCapabilities already implements it, so callers using NativeCapabilities are unaffected. PR title carries the ! marker accordingly.
  • Selection policy stays with the caller — there is no env-reading helper in libdatadog (an earlier recommended_log_output() was removed per review; reading env from libdatadog has caused production crashes). The SDK detects Lambda/agent/extension itself and calls set_output_to_log.
  • meta_struct is intentionally omitted (raw msgpack the log intake can't interpret), matching the reference exporters.
  • Writes are synchronous/blocking — intended for single-threaded serverless runtimes where there is no shared async reactor to stall. Log output takes precedence over an OTLP endpoint if both are configured.
  • No new third-party dependencies (serde_json already in tree) → no Cargo.lock / LICENSE-3rdparty.csv churn.

How to test the change?

cargo nextest run -p libdd-trace-utils -p libdd-data-pipeline -p libdd-data-pipeline-ffi -E '!test(tracing_integration_tests::)'
cargo +stable clippy -p libdd-capabilities -p libdd-capabilities-impl -p libdd-trace-utils -p libdd-data-pipeline -p libdd-data-pipeline-ffi --all-targets --all-features -- -D warnings
cargo ffi-test   # FFI crate touched

Key tests:

  • json_log_encoder — golden bytes, Forwarder is_trace contract, hex (incl. 128-bit), size-cap batching, oversize-drop, non-finite-metric → null, multi-trace flatten, span_links/span_events present-case.
  • trace_exporter::tests::test_log_mode_send_writes_forwarder_json — full send(msgpack) → decode → log branch → capability bytes (via a capturing test capability).
  • trace_exporter::tests::test_log_mode_makes_no_agent_requests — zero agent calls + info_fetcher not spawned in log mode.
  • log_writer helper tests; FFI config_output_to_log_test.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 3041 documentation warning(s) found

📦 libdd-capabilities-impl - 182 warning(s)

📦 libdd-capabilities - 12 warning(s)

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

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

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


Updated: 2026-06-05 20:26:33 UTC | Commit: ce0fde4 | missing-docs job results

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Clippy Allow Annotation Report

Comparing clippy allow annotations between branches:

  • Base Branch: origin/main
  • PR Branch: origin/bengl/trace-log-exporter

Summary by Rule

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

Annotation Counts by File

File Base Branch PR Branch Change
libdd-data-pipeline/src/trace_buffer/mod.rs 1 1 No change (0%)
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 21 21 No change (0%)
datadog-live-debugger 6 6 No change (0%)
datadog-live-debugger-ffi 10 10 No change (0%)
datadog-profiling-replayer 4 4 No change (0%)
datadog-remote-config 4 3 ✅ -1 (-25.0%)
datadog-sidecar 58 57 ✅ -1 (-1.7%)
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-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 13 13 No change (0%)
Total 198 196 ✅ -2 (-1.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 3, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

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

📦 libdd-capabilities-impl - 4 error(s)

Show output
error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:64:1
   │
64 │ 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

error[vulnerability]: Name constraints for URI names were incorrectly accepted
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:75:1
   │
75 │ 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-common v4.2.0 (*)
         └── tokio-rustls v0.26.0
             ├── hyper-rustls v0.27.7 (*)
             └── libdd-common v4.2.0 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:75:1
   │
75 │ 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-common v4.2.0 (*)
         └── tokio-rustls v0.26.0
             ├── hyper-rustls v0.27.7 (*)
             └── libdd-common v4.2.0 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:75:1
   │
75 │ 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-common v4.2.0 (*)
         └── tokio-rustls v0.26.0
             ├── hyper-rustls v0.27.7 (*)
             └── libdd-common v4.2.0 (*)

advisories FAILED, bans ok, sources ok

📦 libdd-capabilities - ✅ No issues

📦 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:222:1
    │
222 │ 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 v5.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 v5.0.0 (*)
      │   │   │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
      │   │   │   ├── libdd-telemetry v5.0.0
      │   │   │   │   └── libdd-data-pipeline v5.0.0 (*)
      │   │   │   └── libdd-trace-stats v4.0.0
      │   │   │       └── libdd-data-pipeline v5.0.0 (*)
      │   │   ├── libdd-trace-stats v4.0.0 (*)
      │   │   └── libdd-trace-utils v7.0.0
      │   │       ├── libdd-data-pipeline v5.0.0 (*)
      │   │       ├── (dev) libdd-data-pipeline-ffi v35.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v3.1.0
      │   │       │   └── libdd-trace-stats v4.0.0 (*)
      │   │       ├── libdd-trace-stats v4.0.0 (*)
      │   │       └── (dev) libdd-trace-utils v7.0.0 (*)
      │   ├── libdd-common-ffi v35.0.0
      │   │   └── libdd-data-pipeline-ffi v35.0.0 (*)
      │   ├── libdd-data-pipeline v5.0.0 (*)
      │   ├── libdd-dogstatsd-client v3.0.0
      │   │   └── libdd-data-pipeline v5.0.0 (*)
      │   ├── libdd-shared-runtime v1.0.0 (*)
      │   ├── libdd-telemetry v5.0.0 (*)
      │   ├── libdd-trace-obfuscation v3.1.0 (*)
      │   ├── libdd-trace-stats v4.0.0 (*)
      │   └── libdd-trace-utils v7.0.0 (*)
      ├── (dev) libdd-data-pipeline v5.0.0 (*)
      ├── (dev) libdd-trace-normalization v2.0.0
      │   └── libdd-trace-utils v7.0.0 (*)
      ├── (dev) libdd-trace-stats v4.0.0 (*)
      ├── libdd-trace-utils v7.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── libdd-data-pipeline v5.0.0 (*)
              ├── libdd-data-pipeline-ffi v35.0.0 (*)
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v7.0.0 (*)

error[vulnerability]: Name constraints for URI names were incorrectly accepted
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:246:1
    │
246 │ 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 v5.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 v5.0.0 (*)
          │       │   │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
          │       │   │   ├── libdd-telemetry v5.0.0
          │       │   │   │   └── libdd-data-pipeline v5.0.0 (*)
          │       │   │   └── libdd-trace-stats v4.0.0
          │       │   │       └── libdd-data-pipeline v5.0.0 (*)
          │       │   ├── libdd-trace-stats v4.0.0 (*)
          │       │   └── libdd-trace-utils v7.0.0
          │       │       ├── libdd-data-pipeline v5.0.0 (*)
          │       │       ├── (dev) libdd-data-pipeline-ffi v35.0.0 (*)
          │       │       ├── libdd-trace-obfuscation v3.1.0
          │       │       │   └── libdd-trace-stats v4.0.0 (*)
          │       │       ├── libdd-trace-stats v4.0.0 (*)
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       ├── libdd-common-ffi v35.0.0
          │       │   └── libdd-data-pipeline-ffi v35.0.0 (*)
          │       ├── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-dogstatsd-client v3.0.0
          │       │   └── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-shared-runtime v1.0.0 (*)
          │       ├── libdd-telemetry v5.0.0 (*)
          │       ├── libdd-trace-obfuscation v3.1.0 (*)
          │       ├── libdd-trace-stats v4.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:246:1
    │
246 │ 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 v5.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 v5.0.0 (*)
          │       │   │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
          │       │   │   ├── libdd-telemetry v5.0.0
          │       │   │   │   └── libdd-data-pipeline v5.0.0 (*)
          │       │   │   └── libdd-trace-stats v4.0.0
          │       │   │       └── libdd-data-pipeline v5.0.0 (*)
          │       │   ├── libdd-trace-stats v4.0.0 (*)
          │       │   └── libdd-trace-utils v7.0.0
          │       │       ├── libdd-data-pipeline v5.0.0 (*)
          │       │       ├── (dev) libdd-data-pipeline-ffi v35.0.0 (*)
          │       │       ├── libdd-trace-obfuscation v3.1.0
          │       │       │   └── libdd-trace-stats v4.0.0 (*)
          │       │       ├── libdd-trace-stats v4.0.0 (*)
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       ├── libdd-common-ffi v35.0.0
          │       │   └── libdd-data-pipeline-ffi v35.0.0 (*)
          │       ├── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-dogstatsd-client v3.0.0
          │       │   └── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-shared-runtime v1.0.0 (*)
          │       ├── libdd-telemetry v5.0.0 (*)
          │       ├── libdd-trace-obfuscation v3.1.0 (*)
          │       ├── libdd-trace-stats v4.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:246:1
    │
246 │ 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 v5.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 v5.0.0 (*)
          │       │   │   ├── libdd-data-pipeline-ffi v35.0.0 (*)
          │       │   │   ├── libdd-telemetry v5.0.0
          │       │   │   │   └── libdd-data-pipeline v5.0.0 (*)
          │       │   │   └── libdd-trace-stats v4.0.0
          │       │   │       └── libdd-data-pipeline v5.0.0 (*)
          │       │   ├── libdd-trace-stats v4.0.0 (*)
          │       │   └── libdd-trace-utils v7.0.0
          │       │       ├── libdd-data-pipeline v5.0.0 (*)
          │       │       ├── (dev) libdd-data-pipeline-ffi v35.0.0 (*)
          │       │       ├── libdd-trace-obfuscation v3.1.0
          │       │       │   └── libdd-trace-stats v4.0.0 (*)
          │       │       ├── libdd-trace-stats v4.0.0 (*)
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       ├── libdd-common-ffi v35.0.0
          │       │   └── libdd-data-pipeline-ffi v35.0.0 (*)
          │       ├── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-dogstatsd-client v3.0.0
          │       │   └── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-shared-runtime v1.0.0 (*)
          │       ├── libdd-telemetry v5.0.0 (*)
          │       ├── libdd-trace-obfuscation v3.1.0 (*)
          │       ├── libdd-trace-stats v4.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Denial of Service via Stack Exhaustion
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:287:1
    │
287 │ 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 v5.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:214:1
    │
214 │ 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 v5.0.0
      │   │   ├── libdd-shared-runtime v1.0.0
      │   │   │   ├── libdd-data-pipeline v5.0.0 (*)
      │   │   │   ├── libdd-telemetry v5.0.0
      │   │   │   │   └── libdd-data-pipeline v5.0.0 (*)
      │   │   │   └── libdd-trace-stats v4.0.0
      │   │   │       └── libdd-data-pipeline v5.0.0 (*)
      │   │   ├── libdd-trace-stats v4.0.0 (*)
      │   │   └── libdd-trace-utils v7.0.0
      │   │       ├── libdd-data-pipeline v5.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v3.1.0
      │   │       │   └── libdd-trace-stats v4.0.0 (*)
      │   │       ├── libdd-trace-stats v4.0.0 (*)
      │   │       └── (dev) libdd-trace-utils v7.0.0 (*)
      │   ├── libdd-data-pipeline v5.0.0 (*)
      │   ├── libdd-dogstatsd-client v3.0.0
      │   │   └── libdd-data-pipeline v5.0.0 (*)
      │   ├── libdd-shared-runtime v1.0.0 (*)
      │   ├── libdd-telemetry v5.0.0 (*)
      │   ├── libdd-trace-obfuscation v3.1.0 (*)
      │   ├── libdd-trace-stats v4.0.0 (*)
      │   └── libdd-trace-utils v7.0.0 (*)
      ├── (dev) libdd-data-pipeline v5.0.0 (*)
      ├── (dev) libdd-trace-normalization v2.0.0
      │   └── libdd-trace-utils v7.0.0 (*)
      ├── (dev) libdd-trace-stats v4.0.0 (*)
      ├── libdd-trace-utils v7.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── libdd-data-pipeline v5.0.0 (*)
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v7.0.0 (*)

error[vulnerability]: Name constraints for URI names were incorrectly accepted
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:238:1
    │
238 │ 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 v5.0.0
          │       │   ├── libdd-shared-runtime v1.0.0
          │       │   │   ├── libdd-data-pipeline v5.0.0 (*)
          │       │   │   ├── libdd-telemetry v5.0.0
          │       │   │   │   └── libdd-data-pipeline v5.0.0 (*)
          │       │   │   └── libdd-trace-stats v4.0.0
          │       │   │       └── libdd-data-pipeline v5.0.0 (*)
          │       │   ├── libdd-trace-stats v4.0.0 (*)
          │       │   └── libdd-trace-utils v7.0.0
          │       │       ├── libdd-data-pipeline v5.0.0 (*)
          │       │       ├── libdd-trace-obfuscation v3.1.0
          │       │       │   └── libdd-trace-stats v4.0.0 (*)
          │       │       ├── libdd-trace-stats v4.0.0 (*)
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       ├── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-dogstatsd-client v3.0.0
          │       │   └── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-shared-runtime v1.0.0 (*)
          │       ├── libdd-telemetry v5.0.0 (*)
          │       ├── libdd-trace-obfuscation v3.1.0 (*)
          │       ├── libdd-trace-stats v4.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:238:1
    │
238 │ 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 v5.0.0
          │       │   ├── libdd-shared-runtime v1.0.0
          │       │   │   ├── libdd-data-pipeline v5.0.0 (*)
          │       │   │   ├── libdd-telemetry v5.0.0
          │       │   │   │   └── libdd-data-pipeline v5.0.0 (*)
          │       │   │   └── libdd-trace-stats v4.0.0
          │       │   │       └── libdd-data-pipeline v5.0.0 (*)
          │       │   ├── libdd-trace-stats v4.0.0 (*)
          │       │   └── libdd-trace-utils v7.0.0
          │       │       ├── libdd-data-pipeline v5.0.0 (*)
          │       │       ├── libdd-trace-obfuscation v3.1.0
          │       │       │   └── libdd-trace-stats v4.0.0 (*)
          │       │       ├── libdd-trace-stats v4.0.0 (*)
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       ├── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-dogstatsd-client v3.0.0
          │       │   └── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-shared-runtime v1.0.0 (*)
          │       ├── libdd-telemetry v5.0.0 (*)
          │       ├── libdd-trace-obfuscation v3.1.0 (*)
          │       ├── libdd-trace-stats v4.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:238:1
    │
238 │ 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 v5.0.0
          │       │   ├── libdd-shared-runtime v1.0.0
          │       │   │   ├── libdd-data-pipeline v5.0.0 (*)
          │       │   │   ├── libdd-telemetry v5.0.0
          │       │   │   │   └── libdd-data-pipeline v5.0.0 (*)
          │       │   │   └── libdd-trace-stats v4.0.0
          │       │   │       └── libdd-data-pipeline v5.0.0 (*)
          │       │   ├── libdd-trace-stats v4.0.0 (*)
          │       │   └── libdd-trace-utils v7.0.0
          │       │       ├── libdd-data-pipeline v5.0.0 (*)
          │       │       ├── libdd-trace-obfuscation v3.1.0
          │       │       │   └── libdd-trace-stats v4.0.0 (*)
          │       │       ├── libdd-trace-stats v4.0.0 (*)
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       ├── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-dogstatsd-client v3.0.0
          │       │   └── libdd-data-pipeline v5.0.0 (*)
          │       ├── libdd-shared-runtime v1.0.0 (*)
          │       ├── libdd-telemetry v5.0.0 (*)
          │       ├── libdd-trace-obfuscation v3.1.0 (*)
          │       ├── libdd-trace-stats v4.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Denial of Service via Stack Exhaustion
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:278:1
    │
278 │ 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 v5.0.0

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:177:1
    │
177 │ 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 v7.0.0
      │   │       └── (dev) libdd-trace-utils v7.0.0 (*)
      │   └── libdd-trace-utils v7.0.0 (*)
      ├── (dev) libdd-trace-normalization v2.0.0
      │   └── libdd-trace-utils v7.0.0 (*)
      ├── libdd-trace-utils v7.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v7.0.0 (*)

error[vulnerability]: Name constraints for URI names were incorrectly accepted
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ 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 v7.0.0
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Name constraints were accepted for certificates asserting a wildcard name
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ 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 v7.0.0
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

error[vulnerability]: Reachable panic in certificate revocation list parsing
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:199:1
    │
199 │ 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 v7.0.0
          │       │       └── (dev) libdd-trace-utils v7.0.0 (*)
          │       └── libdd-trace-utils v7.0.0 (*)
          ├── libdd-common v4.2.0 (*)
          └── tokio-rustls v0.26.0
              ├── hyper-rustls v0.27.7 (*)
              └── libdd-common v4.2.0 (*)

advisories FAILED, bans ok, sources ok

Updated: 2026-06-05 20:27:48 UTC | Commit: ce0fde4 | dependency-check job results

@datadog-prod-us1-5

datadog-prod-us1-5 Bot commented Jun 3, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 93.53%
Overall Coverage: 73.69% (+0.14%)

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

@codecov-commenter

codecov-commenter commented Jun 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.53312% with 41 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.68%. Comparing base (a1da9fc) to head (c71fb77).
⚠️ Report is 16 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2074      +/-   ##
==========================================
+ Coverage   73.44%   73.68%   +0.24%     
==========================================
  Files         465      478      +13     
  Lines       77949    79613    +1664     
==========================================
+ Hits        57248    58664    +1416     
- Misses      20701    20949     +248     
Components Coverage Δ
libdd-crashtracker 65.34% <ø> (-0.14%) ⬇️
libdd-crashtracker-ffi 37.68% <ø> (ø)
libdd-alloc 98.77% <ø> (ø)
libdd-data-pipeline 86.30% <85.71%> (-0.85%) ⬇️
libdd-data-pipeline-ffi 73.97% <75.00%> (-3.07%) ⬇️
libdd-common 79.93% <ø> (+0.04%) ⬆️
libdd-common-ffi 74.41% <ø> (ø)
libdd-telemetry 73.34% <ø> (-0.03%) ⬇️
libdd-telemetry-ffi 31.36% <ø> (ø)
libdd-dogstatsd-client 82.64% <ø> (ø)
datadog-ipc 76.36% <ø> (+0.14%) ⬆️
libdd-profiling 81.69% <ø> (ø)
libdd-profiling-ffi 64.79% <ø> (ø)
libdd-sampling 97.48% <ø> (+0.06%) ⬆️
datadog-sidecar 36.51% <ø> (+1.89%) ⬆️
datdog-sidecar-ffi 12.23% <ø> (+3.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.76% <98.78%> (+0.54%) ⬆️
libdd-tracer-flare 86.57% <ø> (-0.31%) ⬇️
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.

@bengl bengl force-pushed the bengl/trace-log-exporter branch from ca7c877 to a090331 Compare June 3, 2026 15:16
@dd-octo-sts

dd-octo-sts Bot commented Jun 3, 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 82.91 MB 83.15 MB +.28% (+242.70 KB) 🔍
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.63 MB 7.63 MB +0% (+48 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.26 MB 10.26 MB +.06% (+6.33 KB) 🔍
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 93.99 MB 94.23 MB +.25% (+250.11 KB) 🔍
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 24.54 MB 24.61 MB +.30% (+76.00 KB) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 83.96 KB 84.32 KB +.41% (+360 B) 🔍
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 178.18 MB 178.51 MB +.18% (+336.00 KB) 🔍
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 913.88 MB 915.16 MB +.14% (+1.28 MB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.03 MB 8.05 MB +.23% (+19.00 KB) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 83.96 KB 84.32 KB +.41% (+360 B) 🔍
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 23.77 MB 23.84 MB +.29% (+72.00 KB) 🔍
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 47.42 MB 47.54 MB +.23% (+115.06 KB) 🔍
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 21.26 MB 21.32 MB +.31% (+69.00 KB) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 85.29 KB 85.64 KB +.41% (+364 B) 🔍
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 182.11 MB 182.47 MB +.19% (+368.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 906.50 MB 907.87 MB +.15% (+1.36 MB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.20 MB 6.22 MB +.29% (+18.50 KB) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 85.29 KB 85.64 KB +.41% (+364 B) 🔍
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 25.48 MB 25.56 MB +.30% (+80.00 KB) 🔍
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 45.07 MB 45.19 MB +.26% (+123.04 KB) 🔍
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 73.94 MB 74.15 MB +.28% (+217.68 KB) 🔍
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.53 MB 8.55 MB +.18% (+16.03 KB) 🔍
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 89.34 MB 89.56 MB +.24% (+228.54 KB) 🔍
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.37 MB 10.39 MB +.19% (+20.68 KB) 🔍

@bengl bengl force-pushed the bengl/trace-log-exporter branch from a090331 to cb8bad8 Compare June 3, 2026 15:59
@bengl bengl marked this pull request as ready for review June 3, 2026 16:08
@bengl bengl requested review from a team as code owners June 3, 2026 16:08

@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: cb8bad815b

ℹ️ 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-data-pipeline/src/serverless.rs Outdated
Comment on lines +27 to +31
const AGENT_ENDPOINT_ENV_VARS: [&str; 3] = [
"DD_AGENT_HOST",
"DD_TRACE_AGENT_URL",
"DATADOG_TRACE_AGENT_HOSTNAME",
];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include DD_TRACE_AGENT_PORT in endpoint detection

When this helper is used in Lambda, a deployment that sets only DD_TRACE_AGENT_PORT to point at a non-default local/extension agent is still classified as having no explicit agent endpoint, so recommended_log_output() returns true and callers may switch to stdout instead of the configured agent. Other libdatadog config paths treat DD_TRACE_AGENT_PORT as part of trace-agent endpoint resolution (for example telemetry/crashtracker read it alongside DD_AGENT_HOST and DD_TRACE_AGENT_URL), so this list should include it to avoid misrouting traces in that configuration.

Useful? React with 👍 / 👎.

Comment thread libdd-data-pipeline/src/serverless.rs Outdated
fn has_explicit_agent_endpoint() -> bool {
AGENT_ENDPOINT_ENV_VARS
.iter()
.any(|var| matches!(env::var(var), Ok(value) if !value.is_empty()))

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.

getting / setting env vars in libdatadog should be avoided, it's led to production crashes in the past. (See here and here). It's best if the SDKs just pass us the values via the builder.

/// which serializes spans directly to stdout.
#[cfg(not(target_arch = "wasm32"))]
pub fn send_trace_chunks<T: TraceData>(
pub fn send_trace_chunks<T: TraceData + serde::Serialize>(

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.

@iunanua (asking you since you've been working on the semver checks recently) - I'm curious why semver checks aren't failing here? Shouldn't this be considered a breaking change?

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.

It is clearly a breaking change, if the parent modules of this one are public


/// Create a writer targeting a custom sink (used in tests).
#[cfg(test)]
pub(crate) fn with_sink(out: Box<dyn Write + Send>, max_line_size: usize) -> Self {

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 currently gated to #[cfg(test)]. Isn't this going to be needed as part of the public API in order for this to work with wasm? I don't think libdatadog can write to stdout when wasm is the target?

And speaking of wasm, should we be leveraging the capabilities crate for the log writer?

// until the page/module is torn down).
#[cfg(target_arch = "wasm32")]
let _ = info_fetcher_handle;
let _ = &info_fetcher_handle;

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.

I feel this is useless, because instead of dropping the info_fetcher_handle, we drop a reference to it, which doesn't do much. Was this change intentional?

/// flush. On a multi-threaded async runtime this can stall the reactor, so log
/// mode is intended for serverless / current-thread runtimes (e.g. AWS Lambda).
pub(crate) struct LogTraceWriter {
out: Mutex<Box<dyn Write + Send>>,

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.

I think stdout() is already using a mutex internally. Since it's Send + Sync and &Stdout: Write, I believe you can just use Stdout here without an outer mutex, if we always send to Stdout.


/// Create a writer targeting a custom sink (used in tests).
#[cfg(test)]
pub(crate) fn with_sink(out: Box<dyn Write + Send>, max_line_size: usize) -> Self {

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.

Ah, you need a more generic form for tests... we could define enum Sink { Stdout(Stdout), Other(Mutex<Box<dyn Write + Send>>). Not sure it's worth it, if the mutex is never contended and just here to please the compiler, though.

/// which serializes spans directly to stdout.
#[cfg(not(target_arch = "wasm32"))]
pub fn send_trace_chunks<T: TraceData>(
pub fn send_trace_chunks<T: TraceData + serde::Serialize>(

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.

It is clearly a breaking change, if the parent modules of this one are public

"Wrote traces to log exporter"
);
return Ok(AgentResponse::Unchanged);
}

@yannham yannham Jun 4, 2026

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.

nitpick: since this is a totally different codepath that returns early, might be clearer to move that logic into its own synchronous helper (rustc is pretty good at inlining local functions, so this should be free).

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.

nitpick: since this is a totally different codepath that returns early, might be clearer to move that logic into its own synchronous helper (rustc is pretty good at inlining local functions, so this should be free).

Up this nitpick (although not blocking, I'll let you decide);


/// Shared in-memory sink for asserting bytes written in log-export mode.
#[derive(Clone, Default)]
struct SharedSink(std::sync::Arc<std::sync::Mutex<Vec<u8>>>);

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.

I think Arc is imported already? At least in the parent module?

Suggested change
struct SharedSink(std::sync::Arc<std::sync::Mutex<Vec<u8>>>);
struct SharedSink(Arc<std::sync::Mutex<Vec<u8>>>);

Comment thread libdd-data-pipeline/src/serverless.rs Outdated
/// deliberately not exposed over the FFI: host SDKs typically already have their
/// own serverless/agent detection and may implement their own recommendation.
pub fn recommended_log_output() -> bool {
recommended_log_output_inner(Path::new(DATADOG_EXTENSION_PATH))

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.

Nitpick: should probably inline this function here. It's not like the outer function adds much logic/wrapping.

Comment on lines +83 to +100
if has_type {
len += 1;
}
if !span.meta.is_empty() {
len += 1;
}
if !span.metrics.is_empty() {
len += 1;
}
// `meta_struct` is intentionally NOT emitted: it holds raw msgpack bytes
// that would serialize as a JSON number array the intake cannot interpret.
// The reference log exporters (JS/Go/Py/Java) omit it as well.
if !span.span_links.is_empty() {
len += 1;
}
if !span.span_events.is_empty() {
len += 1;
}

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.

Suggested change
if has_type {
len += 1;
}
if !span.meta.is_empty() {
len += 1;
}
if !span.metrics.is_empty() {
len += 1;
}
// `meta_struct` is intentionally NOT emitted: it holds raw msgpack bytes
// that would serialize as a JSON number array the intake cannot interpret.
// The reference log exporters (JS/Go/Py/Java) omit it as well.
if !span.span_links.is_empty() {
len += 1;
}
if !span.span_events.is_empty() {
len += 1;
}
len += has_type as usize;
len += (!span.meta.is_empty()) as usize;
len += (!span.metrics.is_empty()) as usize;
// `meta_struct` is intentionally NOT emitted: it holds raw msgpack bytes
// that would serialize as a JSON number array the intake cannot interpret.
// The reference log exporters (JS/Go/Py/Java) omit it as well.
len += (!span.span_links.is_empty()) as usize;
len += (!span.span_events.is_empty()) as usize;

@bengl bengl force-pushed the bengl/trace-log-exporter branch from cb8bad8 to bc7d64d Compare June 4, 2026 13:58
@bengl bengl requested a review from a team as a code owner June 4, 2026 13:58
@bengl bengl force-pushed the bengl/trace-log-exporter branch 2 times, most recently from b7ac109 to 7a39e74 Compare June 4, 2026 15:46
@bengl bengl changed the title feat(data-pipeline): add stdout log trace exporter feat(data-pipeline)!: add stdout log trace exporter Jun 4, 2026
/// synchronous/blocking, so this mode targets single-threaded serverless
/// runtimes where blocking stdout writes do not stall a shared async reactor.
///
/// Takes precedence over an OTLP endpoint: if both this and `set_otlp_endpoint`

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 think this is non-blocking and can be addressed in a separate PR...

I'm not a fan of the exporter containing precedence logic for configuration. I left a similar comment on @paullegranddc's agentless PR. I believe config logic should live in the SDKs as much as possible, and if the builder receives conflicting config settings, we should return an error. If we want to support precedence to avoid setup friction for customers that should be handled by the SDKs. I don't think there is any harm in merging it as is for now. Let's just capture it in a Jira ticket.

// The handle is currently only tracked for shutdown on native; on wasm
// it is dropped here (the worker keeps running on the JS event loop
// until the page/module is torn down).
// In log-export mode there is no agent to poll; skip spawning the worker

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 left a comment about agent info and telemetry workers being unnecessarily spawned in @paullegranddc's agentless PR. Beyond the scope of this PR, but after these two PRs land we should discuss refactoring the builder a little bit to handle this a bit more elegantly.

assert!(out.is_empty());
}

/// Mirrors the Datadog Forwarder `is_trace` detection contract (spec §6.1):

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.

minor: Since these are technically public docs, if we are going to refer to specs in them by section, the spec should be public too. There is an rfc folder in the libdatadog workspace where you can place the spec as markdown and link to. Alternatively, you could just not mention the spec in the rustdoc comments and not worry about it.

@ekump ekump Jun 5, 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.

Oh, hold on, this is a test. There shouldn't be rustdoc comments at all. I'd suggest just changing the /// to //. I don't have any issue with the spec language in the comment if it's just a code comment and not a rustdoc comment.

@ekump ekump left a comment

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.

A couple of minor comments, mostly calling out future work for the team. LGTM.

@yannham yannham 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.

I like the log capability, even is slightly more verbose, since we get mocking cleanly. Beside one previous nitpick that still applies, LGTM;

// event loop until the page/module is torn down).
#[cfg(target_arch = "wasm32")]
let _ = info_fetcher_handle;
drop(info_fetcher_handle);

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.

Claude can't refrain from rewriting unrelated stuff with bad taste, can't he 😛 (I'm mostly joking, I don't care what syntax people use to drop value, although I do personally prefer the former)

"Wrote traces to log exporter"
);
return Ok(AgentResponse::Unchanged);
}

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.

nitpick: since this is a totally different codepath that returns early, might be clearer to move that logic into its own synchronous helper (rustc is pretty good at inlining local functions, so this should be free).

Up this nitpick (although not blocking, I'll let you decide);

Add a "log exporter" transport that writes traces as newline-delimited
JSON to stdout in the format consumed by the Datadog Forwarder, instead
of sending them to an agent over HTTP. This is the serverless fallback
used in AWS Lambda when no Datadog agent or Lambda extension is
reachable, matching the log writers in dd-trace-js/py/go/java.

- json_log_encoder (libdd-trace-utils): encodes spans to
  {"traces":[[...]]} lines with lowercase hex ids (incl. 128-bit),
  integer error, ns start/duration, empty-field omission, and greedy
  256 KiB line batching that drops oversize single spans.
- TraceExporterBuilder::set_output_to_log selects a stdout destination
  that bypasses agent-info polling, client-side stats, V1 negotiation,
  and telemetry. Exposed over FFI as
  ddog_trace_exporter_config_set_output_to_log.
- The write goes through a new LogWriterCapability so the transport also
  works on wasm (where the host, e.g. JavaScript, supplies the sink);
  the native capability writes to stdout.

Writes are synchronous and intended for single-threaded serverless
runtimes. meta_struct is omitted (raw msgpack the log intake can't read).

BREAKING CHANGE: TraceExporter<C> (and TraceExporterBuilder::build /
build_async and trace_buffer::DefaultExport<C>) now require
C: LogWriterCapability. Callers using a custom capability bundle must
implement libdd_capabilities::LogWriterCapability; NativeCapabilities
already implements it, so callers using NativeCapabilities are unaffected.
@bengl bengl force-pushed the bengl/trace-log-exporter branch from 7a39e74 to c71fb77 Compare June 5, 2026 20:23
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