Skip to content

feat(data-pipeline): OTLP gRPC trace export#2171

Open
bm1549 wants to merge 18 commits into
mainfrom
brian.marks/otlp-grpc-trace-export
Open

feat(data-pipeline): OTLP gRPC trace export#2171
bm1549 wants to merge 18 commits into
mainfrom
brian.marks/otlp-grpc-trace-export

Conversation

@bm1549

@bm1549 bm1549 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds OTLP gRPC as a third trace-export transport alongside HTTP/JSON and HTTP/protobuf, selectable via the OTel-standard OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc. A lazy tonic Channel is built from the configured endpoint at builder time; send_trace_chunks_inner dispatches through a new OtlpExportMode enum to either the existing HTTP path or the gRPC path, which sends an ExportTraceServiceRequest over tonic::client::Grpc.

Motivation

libdatadog's OTLP trace export was HTTP-only. Java and .NET already do gRPC OTLP by hand; PHP, Python, Ruby, and Rust all export through libdatadog FFI, so adding gRPC here unblocks all four at once, and lets SDKs honor OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc instead of warning or coercing it to HTTP.

Additional Notes

  • Implementation plan (Datadog-internal, AppGate-gated): https://chonk.us1.prod.dog/v2/get/chonk-uploads-prod/brian.marks/e350edc5-c454-4625-a531-12f6c7cb2e17 — the design and task breakdown this PR was built from.
  • OtlpExportMode { Http(OtlpTraceConfig), Grpc(OtlpGrpcTransport) } replaces the otlp_config field; the variant is chosen at build time and is mutually exclusive.
  • tonic 0.14 with default-features = false, features = ["transport","codegen"] (the prost feature doesn't exist in 0.14; codegen carries the prost integration). A small ProstCodecImpl stands in for the ProstCodec that 0.14 dropped from the public API.
  • Grpc::ready().await is driven before unary(): tonic's Channel is a tower Buffer that panics if call precedes poll_ready; both are inside one tokio::time::timeout so connect and RPC share the deadline.
  • Plaintext only: https:// endpoints are rejected at build time with a clear error (use a TLS-terminating sidecar). Retry on transient gRPC status is out of scope for v1 (TODO left in place).
  • The test-session token and datadog-client-computed-stats header are carried through as gRPC metadata.

How to test the change?

  • cargo nextest run -p libdd-data-pipeline -p libdd-data-pipeline-ffi (204 tests), cargo test --doc, clippy, and fmt pass. An in-process h2 server test (test_trace_exporter_otlp_grpc.rs) drives a real gRPC send and asserts the server decodes an ExportTraceServiceRequest with the expected service.name; builder and FFI tests cover grpc acceptance and https:// rejection.
  • End-to-end through dd-trace-py (local build consuming this branch): emitted OTLP/gRPC traces through a local Agent's OTLP gRPC receiver (:4317) to the backend. Spans landed under service:verify-grpc-1454: operation grpc.verify.op, resources checkout/payment/inventory, tagged otlp.transport:grpc (1523 hits via trace.grpc.verify.op.hits, 0 trace-writer errors). A known-good OpenTelemetry SDK gRPC client through the same Agent produced the same result.

BREAKING CHANGE: adds the OtlpProtocol::Grpc variant to an exhaustive public enum, and embedding a tonic Channel in TraceExporter drops its UnwindSafe/RefUnwindSafe auto-trait impls. libdatadog consumers pin by version, so they pick this up on the next release.

@bm1549 bm1549 added the AI Generated PR largely written by AI tools label Jun 26, 2026
@datadog-official

datadog-official Bot commented Jun 26, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 89.14%
Overall Coverage: 74.45% (+0.06%)

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

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 2519 documentation warning(s) found

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

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


Updated: 2026-07-10 22:37:56 UTC | Commit: ce09c26 | missing-docs job results

@github-actions

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-grpc-trace-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 22 No change (0%)
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 6 6 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 11 No change (0%)
Total 182 182 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 26, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

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

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

Show output
error[vulnerability]: Invalid pointer dereference in `fmt::Pointer` impl for `Atomic` and `Shared` when the underlying pointer is invalid
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:78:1
   │
78 │ crossbeam-epoch 0.9.18 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
   │
   ├ ID: RUSTSEC-2026-0204
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0204
   ├ Affected versions of `fmt::Display` dereference the underlying pointer. This causes a invalid pointer dereference e.g., when a pointer created with `Atomic::null` or `Shared::null`. `fmt::Debug` impls and pre-0.9 `fmt::Display` impls, which do not dereference pointers, are not affected by this issue.
   ├ Announcement: https://github.com/crossbeam-rs/crossbeam/pull/1276
   ├ Solution: Upgrade to >=0.9.20 (try `cargo update -p crossbeam-epoch`)
   ├ crossbeam-epoch v0.9.18
     └── crossbeam-deque v0.8.5
         └── rayon-core v1.12.1
             └── rayon v1.10.0
                 └── criterion v0.5.1
                     ├── libdd-common v5.1.0
                     │   ├── libdd-capabilities-impl v3.0.0
                     │   │   ├── libdd-data-pipeline v7.0.0
                     │   │   │   └── libdd-data-pipeline-ffi v37.0.0
                     │   │   ├── libdd-data-pipeline-ffi v37.0.0 (*)
                     │   │   ├── libdd-shared-runtime v2.0.0
                     │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   │   │   ├── libdd-data-pipeline-ffi v37.0.0 (*)
                     │   │   │   ├── libdd-telemetry v6.0.0
                     │   │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   │   │   │   └── libdd-trace-stats v6.0.0
                     │   │   │   │       └── libdd-data-pipeline v7.0.0 (*)
                     │   │   │   └── libdd-trace-stats v6.0.0 (*)
                     │   │   ├── libdd-trace-stats v6.0.0 (*)
                     │   │   └── libdd-trace-utils v9.0.0
                     │   │       ├── libdd-data-pipeline v7.0.0 (*)
                     │   │       ├── (dev) libdd-data-pipeline-ffi v37.0.0 (*)
                     │   │       ├── libdd-trace-obfuscation v5.0.0
                     │   │       │   └── libdd-trace-stats v6.0.0 (*)
                     │   │       ├── libdd-trace-stats v6.0.0 (*)
                     │   │       └── (dev) libdd-trace-utils v9.0.0 (*)
                     │   ├── libdd-common-ffi v37.0.0
                     │   │   └── libdd-data-pipeline-ffi v37.0.0 (*)
                     │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   ├── libdd-dogstatsd-client v4.0.0
                     │   │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   │   └── libdd-trace-stats v6.0.0 (*)
                     │   ├── libdd-shared-runtime v2.0.0 (*)
                     │   ├── libdd-telemetry v6.0.0 (*)
                     │   ├── libdd-trace-obfuscation v5.0.0 (*)
                     │   ├── libdd-trace-stats v6.0.0 (*)
                     │   └── libdd-trace-utils v9.0.0 (*)
                     ├── (dev) libdd-data-pipeline v7.0.0 (*)
                     ├── (dev) libdd-ddsketch v1.1.0
                     │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   ├── libdd-telemetry v6.0.0 (*)
                     │   └── libdd-trace-stats v6.0.0 (*)
                     ├── (dev) libdd-trace-normalization v3.0.0
                     │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   └── libdd-trace-utils v9.0.0 (*)
                     ├── (dev) libdd-trace-obfuscation v5.0.0 (*)
                     ├── (dev) libdd-trace-stats v6.0.0 (*)
                     └── (dev) libdd-trace-utils v9.0.0 (*)

error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:227:1
    │
227 │ 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 v5.1.0
      │   ├── libdd-capabilities-impl v3.0.0
      │   │   ├── libdd-data-pipeline v7.0.0
      │   │   │   └── libdd-data-pipeline-ffi v37.0.0
      │   │   ├── libdd-data-pipeline-ffi v37.0.0 (*)
      │   │   ├── libdd-shared-runtime v2.0.0
      │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
      │   │   │   ├── libdd-data-pipeline-ffi v37.0.0 (*)
      │   │   │   ├── libdd-telemetry v6.0.0
      │   │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
      │   │   │   │   └── libdd-trace-stats v6.0.0
      │   │   │   │       └── libdd-data-pipeline v7.0.0 (*)
      │   │   │   └── libdd-trace-stats v6.0.0 (*)
      │   │   ├── libdd-trace-stats v6.0.0 (*)
      │   │   └── libdd-trace-utils v9.0.0
      │   │       ├── libdd-data-pipeline v7.0.0 (*)
      │   │       ├── (dev) libdd-data-pipeline-ffi v37.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v5.0.0
      │   │       │   └── libdd-trace-stats v6.0.0 (*)
      │   │       ├── libdd-trace-stats v6.0.0 (*)
      │   │       └── (dev) libdd-trace-utils v9.0.0 (*)
      │   ├── libdd-common-ffi v37.0.0
      │   │   └── libdd-data-pipeline-ffi v37.0.0 (*)
      │   ├── libdd-data-pipeline v7.0.0 (*)
      │   ├── libdd-dogstatsd-client v4.0.0
      │   │   ├── libdd-data-pipeline v7.0.0 (*)
      │   │   └── libdd-trace-stats v6.0.0 (*)
      │   ├── libdd-shared-runtime v2.0.0 (*)
      │   ├── libdd-telemetry v6.0.0 (*)
      │   ├── libdd-trace-obfuscation v5.0.0 (*)
      │   ├── libdd-trace-stats v6.0.0 (*)
      │   └── libdd-trace-utils v9.0.0 (*)
      ├── (dev) libdd-data-pipeline v7.0.0 (*)
      ├── (dev) libdd-ddsketch v1.1.0
      │   ├── libdd-data-pipeline v7.0.0 (*)
      │   ├── libdd-telemetry v6.0.0 (*)
      │   └── libdd-trace-stats v6.0.0 (*)
      ├── (dev) libdd-trace-normalization v3.0.0
      │   ├── libdd-data-pipeline v7.0.0 (*)
      │   └── libdd-trace-utils v9.0.0 (*)
      ├── (dev) libdd-trace-stats v6.0.0 (*)
      ├── libdd-trace-utils v9.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── libdd-data-pipeline v7.0.0 (*)
              ├── libdd-data-pipeline-ffi v37.0.0 (*)
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v9.0.0 (*)

error[vulnerability]: Denial of Service via Stack Exhaustion
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:298:1
    │
298 │ 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 v7.0.0
                  └── libdd-data-pipeline-ffi v37.0.0

advisories FAILED, bans ok, sources ok

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

Show output
error[vulnerability]: Invalid pointer dereference in `fmt::Pointer` impl for `Atomic` and `Shared` when the underlying pointer is invalid
   ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:75:1
   │
75 │ crossbeam-epoch 0.9.18 registry+https://github.com/rust-lang/crates.io-index
   │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ security vulnerability detected
   │
   ├ ID: RUSTSEC-2026-0204
   ├ Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0204
   ├ Affected versions of `fmt::Display` dereference the underlying pointer. This causes a invalid pointer dereference e.g., when a pointer created with `Atomic::null` or `Shared::null`. `fmt::Debug` impls and pre-0.9 `fmt::Display` impls, which do not dereference pointers, are not affected by this issue.
   ├ Announcement: https://github.com/crossbeam-rs/crossbeam/pull/1276
   ├ Solution: Upgrade to >=0.9.20 (try `cargo update -p crossbeam-epoch`)
   ├ crossbeam-epoch v0.9.18
     └── crossbeam-deque v0.8.5
         └── rayon-core v1.12.1
             └── rayon v1.10.0
                 └── criterion v0.5.1
                     ├── libdd-common v5.1.0
                     │   ├── libdd-capabilities-impl v3.0.0
                     │   │   ├── libdd-data-pipeline v7.0.0
                     │   │   ├── libdd-shared-runtime v2.0.0
                     │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   │   │   ├── libdd-telemetry v6.0.0
                     │   │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   │   │   │   └── libdd-trace-stats v6.0.0
                     │   │   │   │       └── libdd-data-pipeline v7.0.0 (*)
                     │   │   │   └── libdd-trace-stats v6.0.0 (*)
                     │   │   ├── libdd-trace-stats v6.0.0 (*)
                     │   │   └── libdd-trace-utils v9.0.0
                     │   │       ├── libdd-data-pipeline v7.0.0 (*)
                     │   │       ├── libdd-trace-obfuscation v5.0.0
                     │   │       │   └── libdd-trace-stats v6.0.0 (*)
                     │   │       ├── libdd-trace-stats v6.0.0 (*)
                     │   │       └── (dev) libdd-trace-utils v9.0.0 (*)
                     │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   ├── libdd-dogstatsd-client v4.0.0
                     │   │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   │   └── libdd-trace-stats v6.0.0 (*)
                     │   ├── libdd-shared-runtime v2.0.0 (*)
                     │   ├── libdd-telemetry v6.0.0 (*)
                     │   ├── libdd-trace-obfuscation v5.0.0 (*)
                     │   ├── libdd-trace-stats v6.0.0 (*)
                     │   └── libdd-trace-utils v9.0.0 (*)
                     ├── (dev) libdd-data-pipeline v7.0.0 (*)
                     ├── (dev) libdd-ddsketch v1.1.0
                     │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   ├── libdd-telemetry v6.0.0 (*)
                     │   └── libdd-trace-stats v6.0.0 (*)
                     ├── (dev) libdd-trace-normalization v3.0.0
                     │   ├── libdd-data-pipeline v7.0.0 (*)
                     │   └── libdd-trace-utils v9.0.0 (*)
                     ├── (dev) libdd-trace-obfuscation v5.0.0 (*)
                     ├── (dev) libdd-trace-stats v6.0.0 (*)
                     └── (dev) libdd-trace-utils v9.0.0 (*)

error[unsound]: Rand is unsound with a custom logger using `rand::rng()`
    ┌─ /home/runner/work/libdatadog/libdatadog/Cargo.lock:219:1
    │
219 │ 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 v5.1.0
      │   ├── libdd-capabilities-impl v3.0.0
      │   │   ├── libdd-data-pipeline v7.0.0
      │   │   ├── libdd-shared-runtime v2.0.0
      │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
      │   │   │   ├── libdd-telemetry v6.0.0
      │   │   │   │   ├── libdd-data-pipeline v7.0.0 (*)
      │   │   │   │   └── libdd-trace-stats v6.0.0
      │   │   │   │       └── libdd-data-pipeline v7.0.0 (*)
      │   │   │   └── libdd-trace-stats v6.0.0 (*)
      │   │   ├── libdd-trace-stats v6.0.0 (*)
      │   │   └── libdd-trace-utils v9.0.0
      │   │       ├── libdd-data-pipeline v7.0.0 (*)
      │   │       ├── libdd-trace-obfuscation v5.0.0
      │   │       │   └── libdd-trace-stats v6.0.0 (*)
      │   │       ├── libdd-trace-stats v6.0.0 (*)
      │   │       └── (dev) libdd-trace-utils v9.0.0 (*)
      │   ├── libdd-data-pipeline v7.0.0 (*)
      │   ├── libdd-dogstatsd-client v4.0.0
      │   │   ├── libdd-data-pipeline v7.0.0 (*)
      │   │   └── libdd-trace-stats v6.0.0 (*)
      │   ├── libdd-shared-runtime v2.0.0 (*)
      │   ├── libdd-telemetry v6.0.0 (*)
      │   ├── libdd-trace-obfuscation v5.0.0 (*)
      │   ├── libdd-trace-stats v6.0.0 (*)
      │   └── libdd-trace-utils v9.0.0 (*)
      ├── (dev) libdd-data-pipeline v7.0.0 (*)
      ├── (dev) libdd-ddsketch v1.1.0
      │   ├── libdd-data-pipeline v7.0.0 (*)
      │   ├── libdd-telemetry v6.0.0 (*)
      │   └── libdd-trace-stats v6.0.0 (*)
      ├── (dev) libdd-trace-normalization v3.0.0
      │   ├── libdd-data-pipeline v7.0.0 (*)
      │   └── libdd-trace-utils v9.0.0 (*)
      ├── (dev) libdd-trace-stats v6.0.0 (*)
      ├── libdd-trace-utils v9.0.0 (*)
      └── proptest v1.5.0
          └── (dev) libdd-tinybytes v1.1.1
              ├── libdd-data-pipeline v7.0.0 (*)
              ├── (dev) libdd-tinybytes v1.1.1 (*)
              └── libdd-trace-utils v9.0.0 (*)

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

advisories FAILED, bans ok, sources ok

Updated: 2026-07-10 22:39:09 UTC | Commit: ce09c26 | dependency-check job results

bm1549 added a commit that referenced this pull request Jun 27, 2026
The in-process exporter<->h2-server round trip is too timing-sensitive for
heavily contended CI runners: the client `send` has hit its request timeout on
macos-15 (GitHub) and the alpine/arm release-build matrix (GitLab) across
multiple runs, despite passing locally (20/20) and on less-loaded runners, and
despite the live backend verification in PR #2171 succeeding.

Mark it #[ignore] so it no longer runs in the default CI suites (it can't flake
the PR or burn release-build runner time), while keeping it runnable on demand
via `--run-ignored all`. The gRPC export path stays covered by this crate's unit
tests (ProstCodec, grpc_status_to_error, attach_metadata, build_grpc_channel,
builder dispatch, protocol parse) and by the live backend verification.

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

dd-octo-sts Bot commented Jun 27, 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 84.87 MB 91.22 MB +7.48% (+6.35 MB) 🚨
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 7.82 MB 8.58 MB +9.67% (+775.01 KB) 🚨
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.44 MB 11.59 MB +11.00% (+1.15 MB) 🚨
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 96.00 MB 102.49 MB +6.76% (+6.49 MB) 🚨
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 25.05 MB 27.54 MB +9.92% (+2.48 MB) 🚨
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 87.68 KB 87.68 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 182.80 MB 196.31 MB +7.38% (+13.50 MB) 🚨
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 936.10 MB 1.00 GB +10.46% (+97.92 MB) 🚨
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 8.20 MB 9.17 MB +11.83% (+994.50 KB) 🚨
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 87.68 KB 87.68 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 24.23 MB 26.01 MB +7.38% (+1.78 MB) 🚨
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 48.34 MB 52.84 MB +9.30% (+4.49 MB) 🚨
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 21.71 MB 23.96 MB +10.36% (+2.25 MB) 🚨
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 89.06 KB 89.06 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 186.80 MB 200.84 MB +7.51% (+14.03 MB) 🚨
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 924.73 MB 1020.96 MB +10.40% (+96.23 MB) 🚨
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 6.33 MB 7.09 MB +12.14% (+787.00 KB) 🚨
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 89.06 KB 89.06 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 25.99 MB 27.97 MB +7.60% (+1.97 MB) 🚨
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 45.96 MB 49.88 MB +8.51% (+3.91 MB) 🚨
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 75.64 MB 81.50 MB +7.74% (+5.85 MB) 🚨
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 8.68 MB 9.57 MB +10.24% (+911.03 KB) 🚨
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 91.09 MB 97.03 MB +6.51% (+5.93 MB) 🚨
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 10.57 MB 11.69 MB +10.68% (+1.12 MB) 🚨

@bm1549

bm1549 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Artifact Size Benchmark Report

Expected — ~1 MB from linking tonic's gRPC client. Already minimal: client-only (no axum), hyper/h2/prost already linked, 0 new crates. Could hand-roll over hyper/h2 (like Java/.NET) to reclaim most, but it would add significant complexity. I'd lean towards accepting it unless others feel strongly

@bm1549 bm1549 marked this pull request as ready for review June 29, 2026 17:17
@bm1549 bm1549 requested review from a team as code owners June 29, 2026 17:17
@bm1549 bm1549 requested review from vpellan and removed request for a team June 29, 2026 17:17

@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: 9dcddce271

ℹ️ 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/otlp/grpc_exporter.rs Outdated
Comment thread libdd-data-pipeline/src/otlp/grpc_exporter.rs Outdated
bm1549 and others added 14 commits July 10, 2026 18:03
Adds tonic dependency with transport and codegen features required for
implementing gRPC-based OTLP trace export. Also adds h2 and tokio-stream
as dev dependencies for gRPC test infrastructure.

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

Re-add OtlpProtocol::Grpc (previously removed) with support for gRPC as a
valid export protocol alongside HTTP/JSON and HTTP/Protobuf. Add OtlpGrpcTraceConfig
struct to hold gRPC-specific configuration (endpoint, headers, timeout, semantics flag).

The Grpc variant now parses successfully from "grpc" string and is available for
use by the gRPC exporter implementation (Task 3+).

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

Add grpc_exporter.rs with OtlpGrpcTransport, build_grpc_channel, and
send_otlp_traces_grpc. Implements a minimal ProstCodecImpl since tonic
0.14 removed ProstCodec from its public API. All items are pub(crate);
the dispatch wiring comes in the next task.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Downstream tasks depend on OtlpGrpcTraceConfig, build_grpc_channel,
send_otlp_traces_grpc, and OtlpGrpcTransport. Add public and crate-private
re-exports to libdd-data-pipeline's otlp module.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces `OtlpExportMode` to unify HTTP and gRPC OTLP transport
selection. Renames `TraceExporter.otlp_config` to `otlp: Option<OtlpExportMode>`,
updates the dispatch in `send_trace_chunks_inner` to match on the enum
variant, and adds `send_otlp_grpc_inner` that calls `send_otlp_traces_grpc`
with the pre-built `OtlpGrpcTransport`. Builder updated to wrap the HTTP
config in `OtlpExportMode::Http`; gRPC wiring follows in Task 5.

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

Update TraceExporterBuilder to dispatch to the correct OtlpExportMode at
build time based on otlp_protocol. When OtlpProtocol::Grpc is set and an
endpoint URL is provided, call build_grpc_channel and wrap the result in
OtlpExportMode::Grpc(OtlpGrpcTransport); otherwise fall back to
OtlpExportMode::Http. When no otlp_endpoint is set, otlp is None and the
exporter uses the Datadog agent path.

Also update the set_otlp_protocol doc comment to reflect that grpc is now
a supported protocol string.

Three new builder tests cover: grpc+endpoint succeeds, grpc without
endpoint falls back to agent, and https:// with grpc is rejected at build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Update doc comment, inline comment, and tests for
ddog_trace_exporter_config_set_otlp_protocol to reflect that "grpc" is
now a supported value. Replaces set_otlp_protocol_rejects_grpc_and_unknown
with set_otlp_protocol_accepts_all_three_protocols and
set_otlp_protocol_rejects_unknown; updates config_otlp_protocol_test to
assert "grpc" -> success with OtlpProtocol::Grpc stored.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r Buffer poll contract

Tower's Buffer service requires poll_ready/poll_reserve to be called before
call/send_item. tonic 0.14's Grpc::unary does not call poll_ready internally,
so callers must invoke client.ready().await first. Without this, the exporter
panicked with "send_item called without first calling poll_reserve" on the
first gRPC send. Also removes the now-stale #![allow(dead_code)] annotation
since the gRPC transport is fully wired up.

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

Adds two tests in test_trace_exporter_otlp_grpc.rs:

- grpc_export_sends_decodable_request: spins up an in-process h2 server,
  configures a TraceExporter with OtlpProtocol::Grpc, sends a msgpack-encoded
  trace via spawn_blocking, and asserts the server received a decodable
  ExportTraceServiceRequest with the expected service.name attribute.

- grpc_protocol_string_parses: verifies OtlpProtocol::from_str("grpc") returns
  OtlpProtocol::Grpc, covering the FromStr path without FFI ceremony.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix doc placeholder in OtlpExportMode: [] → [TraceExporter]
- Remove duplicate grpc parse tests (keep grpc_parses_successfully)
- Remove #[allow(dead_code)] from OtlpExportMode (now wired up)
- Remove #[allow(unused_imports)] from otlp/mod.rs re-exports
- Mark OtlpGrpcTraceConfig.endpoint_url with #[allow(dead_code)] (unused by gRPC path)

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

- Move tonic to a cfg(not(target_arch = "wasm32")) dependency and gate the
  grpc_exporter module, OtlpExportMode::Grpc, the builder construction arm, and
  send_otlp_grpc_inner behind the same cfg. tonic's transport (hyper/tokio/socket2)
  does not build for wasm32, which broke `cargo check -p libdd-data-pipeline
  --target wasm32-unknown-unknown --no-default-features`.
- Add #[cfg_attr(miri, ignore)] to build_with_grpc_https_endpoint_rejected, matching
  its sibling builder tests: build() starts the shared runtime whose worker hits a
  syscall Miri cannot execute.
- Raise the e2e gRPC test's per-request timeout (set_connection_timeout) so the
  heavily instrumented coverage build does not time out the in-process round trip.

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

- Attach the `datadog-client-computed-stats` marker as request metadata inside
  send_otlp_traces_grpc (new client_computed_stats arg) instead of cloning the
  whole OtlpGrpcTransport (and its header Vec) on every export.
- Add unit tests for grpc_status_to_error (transient -> Io, application -> Request)
  and attach_metadata (valid header + token, invalid header skipped, stats marker).
- Add a criterion benchmark (benches/otlp_grpc_export.rs) for the gRPC wire-frame
  encoding and end-to-end native-spans -> framed-wire preparation across trace sizes.

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

Addresses pre-push review findings across the OTLP gRPC change:

- builder: on wasm32, reject `OtlpProtocol::Grpc` with a clear error instead of
  falling through to the HTTP arm — which stored `OtlpProtocol::Grpc` in
  `OtlpTraceConfig` and panicked at `encode()`'s `unreachable!()` on first send
  (a panic across the FFI boundary). The unreachable arms are now truly
  unreachable on every target.
- grpc_status_to_error: map `DeadlineExceeded` to `TimedOut` (was
  `ConnectionRefused`); the unit test now asserts the exact error kind.
- ProstDecoder: drain the buffer via `copy_to_bytes`, robust if tonic's
  `DecodeBuf` ever becomes non-contiguous (`chunk()` could truncate).
- extract `build_otlp_resource_info`, shared by the HTTP and gRPC send paths;
  hoist the OTLP drop_chunks/empty-check guard above the dispatch match.
- drop the unused `OtlpGrpcTraceConfig::endpoint_url` field; gate `prost` off
  wasm32 since only the (wasm-gated) gRPC exporter uses it.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The `grpc_export_sends_decodable_request` test timed out (Io::TimedOut at the
full per-request timeout) on the alpine/arm release-build jobs in GitLab CI,
while passing locally and on centos-amd. Root cause: the `#[tokio::test]`
current-thread runtime hosted both the in-process h2 server task and the
`spawn_blocking` exporter coordination, so under parallel CI load the server
task could be starved and the client's send would hang to the timeout.

Run the h2 server on its own OS thread + current-thread runtime, and drive the
exporter's own runtime via `send` directly on the test thread (no ambient async
runtime, so no `spawn_blocking`). The two sides now have independent threads and
runtimes and cannot starve each other. Verified 15/15 runs locally.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
bm1549 and others added 4 commits July 10, 2026 18:06
The previous rewrite blocked the test on `server.join()`, whose
`while h2_conn.accept()` loop only ends when the pooled client connection
closes — which the exporter never does — so the alpine/centos release-build
jobs hung to GitLab's 2h `job_execution_timeout`. It passed locally only
because process exit killed the detached runtime before the join mattered.

Detach the server thread and time-bound every server-side await: a 60s overall
ceiling (so a never-connecting client can't wedge the thread) and a 10s
response-flush drive. The test no longer joins the server — verification comes
from `send` returning Ok (client received grpc-status:0) plus the decoded
request on the channel. 20/20 local runs, ~100ms each.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The in-process exporter<->h2-server round trip is too timing-sensitive for
heavily contended CI runners: the client `send` has hit its request timeout on
macos-15 (GitHub) and the alpine/arm release-build matrix (GitLab) across
multiple runs, despite passing locally (20/20) and on less-loaded runners, and
despite the live backend verification in PR #2171 succeeding.

Mark it #[ignore] so it no longer runs in the default CI suites (it can't flake
the PR or burn release-build runner time), while keeping it runnable on demand
via `--run-ignored all`. The gRPC export path stays covered by this crate's unit
tests (ProstCodec, grpc_status_to_error, attach_metadata, build_grpc_channel,
builder dispatch, protocol parse) and by the live backend verification.

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

Root cause of the CI flakiness (found, not masked): the in-process h2 test
server accepted the stream once, then read the request body inline without
continuing to poll the `server::Connection`. Polling the connection is what
reads incoming frames off the socket and routes DATA to an open stream's body.
When the client's request DATA frame was already buffered during `accept()`
(the common coalesced case) the read returned immediately and the test passed;
when the DATA frame landed *after* `accept()` returned (more likely under load,
as HEADERS and DATA split across socket reads), nothing ever polled the
connection to read it, so `body.data()` hung until the client's request timeout
fired — surfacing as `Io(Kind(TimedOut))` / "Timeout expired" on the contended
macos-15 and alpine/arm runners.

Confirmed by instrumentation (server reached "stream accepted" then stalled 30s
with no body) and by it being independent of the exporter's worker-thread count
(1 vs 4 both failed), ruling out CPU starvation / a product bug.

Fix: keep the `accept()` loop running (which drives the connection and flushes
responses) and handle each Export stream in a spawned task. Reproduced the
failure under 6x CPU oversubscription (24/160 failures) and verified the fix
(160/160, then 120/120, all green) with the default 1-worker runtime.

Reverts the earlier #[ignore] from 69aab62 — the test is correct and robust
now, so it runs in CI again.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@bm1549 bm1549 force-pushed the brian.marks/otlp-grpc-trace-export branch from 9dcddce to 093ed21 Compare July 10, 2026 22:35
@pr-commenter

pr-commenter Bot commented Jul 10, 2026

Copy link
Copy Markdown

Benchmarks

Comparison

Benchmark execution time: 2026-07-10 23:08:22

Comparing candidate commit 093ed21 in PR branch brian.marks/otlp-grpc-trace-export with baseline commit ffd3e80 in branch main.

Found 1 performance improvements and 2 performance regressions! Performance is the same for 139 metrics, 0 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:profile_add_sample_frames_x1000

  • 🟩 execution_time [-177.017µs; -176.069µs] or [-4.187%; -4.164%]

scenario:profiles_dictionary/profile_string_inserts/threads/1

  • 🟥 execution_time [+17.535µs; +21.081µs] or [+5.838%; +7.019%]
  • 🟥 throughput [-224802.722op/s; -187055.384op/s] or [-6.593%; -5.486%]

Benchmark execution time: 2026-07-10 23:26:31

Comparing candidate commit 093ed21 in PR branch brian.marks/otlp-grpc-trace-export with baseline commit ffd3e80 in branch main.

Found 2 performance improvements and 15 performance regressions! Performance is the same for 160 metrics, 10 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

scenario:alloc_free/sampled_system_fast_path/4096

  • 🟩 execution_time [-9.900ns; -9.732ns] or [-9.351%; -9.193%]

scenario:alloc_free/system/4096

  • 🟩 execution_time [-13.919ns; -13.759ns] or [-14.852%; -14.681%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟥 execution_time [+402.060ns; +404.735ns] or [+6.654%; +6.698%]
  • 🟥 throughput [-10390512.289op/s; -10321904.480op/s] or [-6.279%; -6.237%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟥 execution_time [+402.484ns; +405.009ns] or [+6.661%; +6.703%]
  • 🟥 throughput [-10398971.305op/s; -10334366.877op/s] or [-6.283%; -6.244%]

scenario:ddsketch_encode/into_pb/clustered_near_zero

  • 🟥 execution_time [+5.929ns; +6.523ns] or [+17.098%; +18.812%]

scenario:ddsketch_encode/into_pb/collapsing

  • 🟥 execution_time [+5.739ns; +6.794ns] or [+15.011%; +17.770%]

scenario:ddsketch_encode/into_pb/large_values

  • 🟥 execution_time [+5.744ns; +6.886ns] or [+16.340%; +19.588%]

scenario:ddsketch_encode/into_pb/mixed

  • 🟥 execution_time [+5.976ns; +6.704ns] or [+16.620%; +18.645%]

scenario:glob_matcher/ascii_case_insensitive_match/wall_time

  • 🟥 execution_time [+1.994ns; +2.041ns] or [+7.231%; +7.403%]

scenario:glob_matcher/ascii_exact_match/wall_time

  • 🟥 execution_time [+2.620ns; +2.661ns] or [+9.500%; +9.652%]

scenario:glob_matcher/ascii_exact_miss/wall_time

  • 🟥 execution_time [+2.825ns; +2.898ns] or [+23.373%; +23.976%]

scenario:glob_matcher/ascii_wildcard_backtrack_match/wall_time

  • 🟥 execution_time [+10.198ns; +10.217ns] or [+27.721%; +27.771%]

scenario:glob_matcher/ascii_wildcard_heavy_backtrack/wall_time

  • 🟥 execution_time [+9.372ns; +9.415ns] or [+22.935%; +23.041%]

scenario:glob_matcher/ascii_wildcard_question_match/wall_time

  • 🟥 execution_time [+9.355ns; +9.374ns] or [+25.426%; +25.479%]

scenario:glob_matcher/ascii_wildcard_star_match/wall_time

  • 🟥 execution_time [+9.418ns; +9.443ns] or [+25.528%; +25.594%]

Candidate

Omitted due to size.

Baseline

Omitted due to size.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant