feat(data-pipeline)!: OTLP gRPC trace export - #2171
gh-worker-dd-mergequeue-cf854d[bot] merged 10 commits into
Conversation
🎉 All green!🧪 All tests passed 🔄 Datadog auto-retried 2 jobs - 0 passed on retry 🎯 Code Coverage (details) 🔗 Commit SHA: 2b21167 | Docs | View more details | Give us feedback! |
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>
Artifact Size Benchmark Reportaarch64-alpine-linux-musl
aarch64-unknown-linux-gnu
libdatadog-x64-windows
libdatadog-x86-windows
x86_64-alpine-linux-musl
x86_64-unknown-linux-gnu
|
There was a problem hiding this comment.
💡 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".
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>
9dcddce to
093ed21
Compare
BenchmarksComparisonBenchmark execution time: 2026-09-09 17:29:58 Comparing candidate commit 2b21167 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 108 metrics, 0 unstable metrics.
|
There was a problem hiding this comment.
First, apologies for waiting so long before giving you a first review. We'll avoid that kind of delay in the future.
As far as the PR goes, I have left a bunch of comments but there's no big technical blocker on my side. However I can't approve right away because the size impact is quite important. We don't have binary size quality gates (yet), but downstream consumers of libdatadog (tracers) do, which can lead to an unfortunate situation where this would get merged but tracers would be unable to update to future releases.
A first naive question: could/should this be feature-gated? I assume you'd want all tracers to support otlp out of the box, so the answers might be no, bu asking just in case.
A good test for the impact of the binary size increase: would you mind trying to create a PR against dd-trace-py pointing to this PR's libdatadog ref, and see if it triggers the size gates for e.g. serverless?
|
So, we've had a discussion with @VianneyRuhlmann about the whole worker situation. We believe we can side-step the "task in the background that needs to be restared" entirely by plugging in our own |
093ed21 to
812e43b
Compare
## Description When native OTLP trace export fails, `NativeWriter` currently reports its configured Datadog Agent intake URL even though libdatadog attempted the OTLP endpoint. This makes an OTLP protocol or connectivity error look like an Agent fallback. Use the configured OTLP trace endpoint in failure diagnostics whenever OTLP trace export is active. Agent export diagnostics keep their existing behavior. The original investigation also exposed a separate protocol mismatch: released versions send OTLP traces over HTTP/JSON, while the repro targeted the collector's gRPC port. HTTP/protobuf and gRPC support are already tracked by #18609, DataDog/libdatadog#2171, and DataDog/libdatadog#2273; this PR does not duplicate those transport changes. ## Testing - `scripts/run-tests --venv 1ef5a52 -- -- tests/tracer/test_writer.py -k 'native_writer_reports_otlp_intake_endpoint or native_writer_stores_otlp_endpoint'` (Python 3.13; 2 passed) - `scripts/lint checks` - `scripts/lint style -- ddtrace/internal/writer/writer.py tests/tracer/test_writer.py` - `scripts/lint spelling -- releasenotes/notes/fix-otlp-export-error-endpoint-6e7b7c8f756ef3a7.yaml` - `riot run reno lint` ## Risks Low. The change only affects the endpoint displayed in trace-export failure diagnostics when an OTLP endpoint is configured. It does not change routing, serialization, or retry behavior. ## Additional Notes The OTLP/DDOT reference and the original handoff document were corrected separately to record that the old port-4317 reproduction was testing an HTTP exporter against a gRPC receiver. Co-authored-by: munir.abdinur <munir.abdinur@datadoghq.com>
812e43b to
13656d6
Compare
Wires OTLP gRPC trace export into TraceExporter on top of the fork-safe gRPC transport, selectable via OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc. OtlpProtocol gains a Grpc variant; the exporter dispatches through a new OtlpExportMode (Http | Grpc) to either the existing HTTP path or the gRPC transport (send_otlp_traces_grpc), with bounded exponential retry on transient IO matching the HTTP path. The OTLP resource info is built once at construction and shared by both paths. gRPC is native-only; wasm32 rejects it at build time. Includes a public-API end-to-end gRPC export test. BREAKING CHANGE: adds the Grpc variant to the exhaustive public OtlpProtocol enum, so exhaustive matches on it must add an arm. libdatadog consumers pin by version and pick this up on the next release. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
13656d6 to
f0e93c2
Compare
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0e93c2dce
ℹ️ 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".
Default portless HTTP endpoints to port 80 while rejecting ambiguous authorities. Decode google.rpc.RetryInfo locally to avoid another tonic dependency, retry recoverable resource exhaustion with capped exponential delays, and share protobuf requests across attempts.
…-trace-export # Conflicts: # .github/CODEOWNERS
mabdinur
left a comment
There was a problem hiding this comment.
Reviewed the current head, including the per-request gRPC transport lifecycle, endpoint validation, retry/status handling, OTLP metadata, FFI selection, and target gating. Focused compile, format, clippy, tests, docs, and FFI validation pass locally. I found no blocking correctness issues.
a2a1dfb
into
main
…ibdd-data-pipeline, libdd-li... (#2571) <!-- release-proposal-inputs: {"crates":"libdd-capabilities-impl, libdd-common, libdd-data-pipeline, libdd-library-config, libdd-profiling-heap-allocator, libdd-remote-config, libdd-sampling, libdd-shared-runtime, libdd-telemetry, libdd-tinybytes, libdd-trace-utils","main_start_ref":"","level_overrides":"","bypass_standard_checks":false} --> # Release proposal for libdd-capabilities-impl, libdd-common, libdd-data-pipeline, libdd-library-config, libdd-profiling-heap-allocator, libdd-remote-config, libdd-sampling, libdd-shared-runtime, libdd-telemetry, libdd-tinybytes, libdd-trace-utils and their dependencies This PR contains version bumps based on public API changes and commits since last release. ###⚠️ Crates left out of this proposal affected by its major bumps These publishable workspace crates are not part of this release but their dependency requirement was rewritten on this branch while their published version still requires the old major. If they are a dependency on your deployment not including them in the release could result in duplicate packages or symbol incompatibility. - `libdd-capabilities` `3.0.1` → `4.0.0` affects: `libdd-crashtracker`, `libdd-ffe`, `libdd-live-debugger` - `libdd-capabilities-impl` `5.0.0` → `6.0.0` affects: `libdd-crashtracker`, `libdd-live-debugger`, `libdd-tracer-flare` - `libdd-common` `6.0.0` → `7.0.0` affects: `libdd-crashtracker`, `libdd-ffe`, `libdd-http-client`, `libdd-ipc`, `libdd-live-debugger`, `libdd-profiling`, `libdd-tracer-flare` - `libdd-data-pipeline` `10.0.0` → `11.0.0` affects: `libdd-live-debugger` - `libdd-remote-config` `5.0.0` → `6.0.0` affects: `libdd-ffe`, `libdd-live-debugger`, `libdd-tracer-flare` - `libdd-telemetry` `8.0.0` → `9.0.0` affects: `libdd-crashtracker` - `libdd-trace-stats` `9.0.0` → `10.0.0` affects: `libdd-ipc` - `libdd-trace-utils` `12.0.0` → `13.0.0` affects: `libdd-tracer-flare` ## libdd-capabilities **Next version:** `4.0.0` **Semver bump:** `major` **Tag:** `libdd-capabilities-v4.0.0` ### Commits - feat(trace-exporter)!: add API to force flush stats on the trace exporter (#2538) - refactor!: apply small timeout pooling strategy to libdd-http-client as well (#2449) - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-common **Next version:** `7.0.0` **Semver bump:** `major` **Tag:** `libdd-common-v7.0.0` ### Commits - build: enforce workspace-level dependency declarations (#2514) - chore!: remove unused dependencies (v2) (#2511) - chore: move all remaining external deps to workspace-level dependencies (#2476) - chore(libdd-data-pipeline): solve cargo deny [APMSP-3884] (#2318) - fix!: benchmark was doing many samples for deterministic heap usage (#2465) ## libdd-ddsketch **Next version:** `1.1.2` **Semver bump:** `patch` **Tag:** `libdd-ddsketch-v1.1.2` ### Commits - chore: move all remaining external deps to workspace-level dependencies (#2476) - chore(libdd-data-pipeline): solve cargo deny [APMSP-3884] (#2318) ## libdd-profiling-heap-sampler **Next version:** `1.1.0` **Semver bump:** `minor` **Tag:** `libdd-profiling-heap-sampler-v1.1.0` ### Commits - chore: move all remaining external deps to workspace-level dependencies (#2476) - refactor: migrate to workspace dependencies, phase 4 (#2296) - feat(profiling): add USDT semaphores to skip slow path around heap profile sampler (#2266) ## libdd-tinybytes **Next version:** `1.1.4` **Semver bump:** `patch` **Tag:** `libdd-tinybytes-v1.1.4` ### Commits - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-trace-protobuf **Next version:** `5.0.1` **Semver bump:** `patch` **Tag:** `libdd-trace-protobuf-v5.0.1` ### Commits - chore: move all remaining external deps to workspace-level dependencies (#2476) - fix(build): build script change detection (#2467) ## libdd-capabilities-impl **Next version:** `6.0.0` **Semver bump:** `major` **Tag:** `libdd-capabilities-impl-v6.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 ### Commits - refactor!: apply small timeout pooling strategy to libdd-http-client as well (#2449) - fix(sidecar)!: stabilize the sidecar for macos usage (#2475) - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-profiling-heap-allocator **Next version:** `1.1.0` **Semver bump:** `minor` **Tag:** `libdd-profiling-heap-allocator-v1.1.0` ### Commits - refactor(benchmarks): measure allocator thread CPU time (#2500) - refactor: migrate to workspace dependencies, phase 4 (#2296) - feat(profiling): add USDT semaphores to skip slow path around heap profile sampler (#2266) ## libdd-library-config **Next version:** `4.1.0` **Semver bump:** `minor` **Tag:** `libdd-library-config-v4.1.0` ### Commits - chore!: remove unused dependencies (v2) (#2511) - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-trace-normalization **Next version:** `4.1.0` **Semver bump:** `minor` **Tag:** `libdd-trace-normalization-v4.1.0` ### Commits - chore: move all remaining external deps to workspace-level dependencies (#2476) - chore(libdd-data-pipeline): solve cargo deny [APMSP-3884] (#2318) ## libdd-remote-config **Next version:** `6.0.0` **Semver bump:** `major` **Tag:** `libdd-remote-config-v6.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-capabilities-impl`: ^5.0.0 → ^6.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 ### Commits - refactor!: apply small timeout pooling strategy to libdd-http-client as well (#2449) - chore!: remove unused dependencies (v2) (#2511) - fix(rem-cfg)!: remove AsmRawResponseBody (#2540) - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-shared-runtime **Next version:** `5.0.0` **Semver bump:** `major` **Tag:** `libdd-shared-runtime-v5.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-capabilities-impl`: ^5.0.0 → ^6.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 ### Commits - feat(trace-exporter)!: add API to force flush stats on the trace exporter (#2538) - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-trace-utils **Next version:** `13.0.0` **Semver bump:** `major` **Tag:** `libdd-trace-utils-v13.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-capabilities-impl`: ^5.0.0 → ^6.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 ### Commits - fix(trace-utils)!: add forgotten css to agentless v1 encoder (#2557) - fix(otlp): use potential dedupe in otlp serialization path (#2531) - feat(trace-utils)!: add v1-native OTLP encoder brick (#2369) - perf(serialization): bench the actual path used by the trace exporter (#2512) - perf(trace): write agentless JSON directly (#2454) - chore: move all remaining external deps to workspace-level dependencies (#2476) - perf(trace): encode agentless IDs without formatting (#2452) - perf(trace-utils)!: use pooled spans on the send path (#2382) - feat(data-pipeline)!: OTLP gRPC trace export (#2171) - chore(libdd-data-pipeline): solve cargo deny [APMSP-3884] (#2318) - fix!: benchmark was doing many samples for deterministic heap usage (#2465) ## libdd-dogstatsd-client **Next version:** `7.0.0` **Semver bump:** `major` **Tag:** `libdd-dogstatsd-client-v7.0.0` ###⚠️ major bump forced due to: - `libdd-common`: ^6.0.0 → ^7.0.0 - `libdd-shared-runtime`: ^4.0.0 → ^5.0.0 ### Commits - chore: move all remaining external deps to workspace-level dependencies (#2476) ## libdd-telemetry **Next version:** `9.0.0` **Semver bump:** `major` **Tag:** `libdd-telemetry-v9.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 - `libdd-shared-runtime`: ^4.0.0 → ^5.0.0 ### Commits - refactor!: apply small timeout pooling strategy to libdd-http-client as well (#2449) - chore!: remove unused dependencies (v2) (#2511) - chore: move all remaining external deps to workspace-level dependencies (#2476) - fix(telemetry): fall back to the proper intake telemetry domain when direct submission is enabled (#2484) ## libdd-sampling **Next version:** `7.0.0` **Semver bump:** `major` **Tag:** `libdd-sampling-v7.0.0` ###⚠️ major bump forced due to: - `libdd-common`: ^5.2.0 → ^7.0.0 - `libdd-trace-utils`: ^10.1.0 → ^13.0.0 ### Commits - chore(benchmarks): remove batched-loop sampling noise (#2498) - chore: move all remaining external deps to workspace-level dependencies (#2476) - fix!: benchmark was doing many samples for deterministic heap usage (#2465) - feat(trace-utils)!: add from owned to SpanText (#2403) - test(sampling): make rate_limiter thread-safety test deterministic (#2354) ## libdd-trace-obfuscation **Next version:** `9.0.0` **Semver bump:** `major` **Tag:** `libdd-trace-obfuscation-v9.0.0` ###⚠️ major bump forced due to: - `libdd-common`: ^6.0.0 → ^7.0.0 - `libdd-trace-utils`: ^12.0.0 → ^13.0.0 ### Commits - feat(data-pipeline)!: refactor agent's /info obfuscation config format (#2490) - fix(obfuscation): keep URLs whose path or fragment holds a bracket (#2527) - fix(obfuscation): stop forcing serde_json/preserve_order on dependents (#2529) - fix(obfuscation): prevent crash and cap recursion in SQL/HTTP obfuscation (#2441) - chore: move all remaining external deps to workspace-level dependencies (#2476) - fix(data-pipeline-ffi): harden agentless config setters and parse obfuscation config once (#2474) ## libdd-trace-stats **Next version:** `10.0.0` **Semver bump:** `major` **Tag:** `libdd-trace-stats-v10.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-capabilities-impl`: ^5.0.0 → ^6.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 - `libdd-shared-runtime`: ^4.0.0 → ^5.0.0 - `libdd-trace-obfuscation`: ^8.0.0 → ^9.0.0 - `libdd-trace-utils`: ^12.0.0 → ^13.0.0 ### Commits - feat(trace-exporter)!: add API to force flush stats on the trace exporter (#2538) - fix(trace-stats): cardinality limit telemetry name (#2559) - feat(data-pipeline)!: refactor agent's /info obfuscation config format (#2490) - chore!: remove unused dependencies (v2) (#2511) - feat(data-pipeline)!: generate agentless trace stats (#2488) - chore: move all remaining external deps to workspace-level dependencies (#2476) - chore(libdd-data-pipeline): solve cargo deny [APMSP-3884] (#2318) ## libdd-data-pipeline-core **Next version:** `2.0.0` **Semver bump:** `major` **Tag:** `libdd-data-pipeline-core-v2.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 - `libdd-trace-obfuscation`: ^8.0.0 → ^9.0.0 - `libdd-trace-utils`: ^12.0.0 → ^13.0.0 ### Commits - refactor!: apply small timeout pooling strategy to libdd-http-client as well (#2449) - feat(data-pipeline)!: generate agentless trace stats (#2488) - perf(data-pipeline): avoid parsing static entity header names (#2457) - chore: move all remaining external deps to workspace-level dependencies (#2476) - perf(trace-utils)!: use pooled spans on the send path (#2382) ## libdd-data-pipeline **Next version:** `11.0.0` **Semver bump:** `major` **Tag:** `libdd-data-pipeline-v11.0.0` ###⚠️ major bump forced due to: - `libdd-capabilities`: ^3.0.1 → ^4.0.0 - `libdd-capabilities-impl`: ^5.0.0 → ^6.0.0 - `libdd-common`: ^6.0.0 → ^7.0.0 - `libdd-data-pipeline-core`: ^1.0.0 → ^2.0.0 - `libdd-shared-runtime`: ^4.0.0 → ^5.0.0 - `libdd-trace-obfuscation`: ^8.0.0 → ^9.0.0 - `libdd-trace-stats`: ^9.0.0 → ^10.0.0 - `libdd-trace-utils`: ^12.0.0 → ^13.0.0 ### Commits - feat(trace-exporter)!: add API to force flush stats on the trace exporter (#2538) - refactor!: apply small timeout pooling strategy to libdd-http-client as well (#2449) - feat(data-pipeline)!: refactor agent's /info obfuscation config format (#2490) - test(data-pipeline): stop OTLP gRPC post-connect test from hanging (#2549) - chore!: remove unused dependencies (v2) (#2511) - feat(data-pipeline)!: generate agentless trace stats (#2488) - fix(otlp): use potential dedupe in otlp serialization path (#2531) - refactor(benchmarks): isolate enqueue timing in data-pipeline (#2499) - perf(trace): write agentless JSON directly (#2454) - test(data-pipeline): fix flaky OTLP gRPC exporter integration tests (#2505) - chore: move all remaining external deps to workspace-level dependencies (#2476) - perf(trace-utils)!: use pooled spans on the send path (#2382) - feat(data-pipeline)!: OTLP gRPC trace export (#2171) - chore(libdd-data-pipeline): solve cargo deny [APMSP-3884] (#2318) [APMSP-3884]: https://datadoghq.atlassian.net/browse/APMSP-3884?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: paullegranddc <82819397+paullegranddc@users.noreply.github.com>
What does this PR do?
Adds OTLP gRPC as a trace-export transport, selectable with
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpc.OtlpProtocolgains aGrpcvariant, andTraceExporterdispatches throughOtlpExportMode(HttporGrpc). The gRPC path limits response bodies to 4 MiB and reports partial-success responses. Remote-status diagnostics retain the original gRPC code. OTLP resource metadata is built once when the exporter is constructed, including the client-computed-stats marker. gRPC is native-only; wasm32 rejects it during build. The FFI acceptsgrpc, so SDKs using libdatadog can select the transport.The transport validates its dial authority before creating the exporter. Portless
http://endpoints use port 80. Valid explicit DNS and IPv6 ports are preserved; empty hosts, malformed ports, and userinfo are rejected. Retryable gRPC errors use bounded exponential backoff with jitter.RESOURCE_EXHAUSTEDis retried only when the server suppliesgoogle.rpc.RetryInfo. A positive server delay is used as the backoff base when it fits within the 30-second retry budget; longer delays stop retries instead of retrying before the server requested. Zero or missing delays use the existing 100 ms base. Protobuf requests are shared across attempts instead of deep-cloned.The fork-safe gRPC transport primitive landed in #2273. This PR integrates it with the exporter and FFI and includes the transport hardening found during review. Completed responses now win over subsequent connection teardown, and transient HTTP/2 stream resets are classified as retryable transport errors. Remote gRPC statuses keep their code and status classification instead of being reported as local I/O failures. The gRPC path sends the standard libdatadog user-agent and entity headers and emits the native trace-export telemetry now used by the other transports.
Motivation
libdatadog's OTLP trace export was HTTP-only. Java and .NET implement gRPC OTLP separately; PHP, Python, Ruby, and Rust use libdatadog for trace export. Adding gRPC here lets their integrations honor
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=grpcinstead of rejecting it or falling back to another transport.Additional Notes
GrpcServiceover hyper h2c. It creates a connection per request and has no persistent worker, which keeps it safe across forks.OtlpProtocol::from_str("grpc")now succeeds. Adding a variant to the exhaustive public enum is a breaking change, as noted in the commit footer.Cancelled,Aborted,OutOfRange,DataLoss,Unavailable, andDeadlineExceeded) getOTLP_MAX_RETRIES + 1total attempts.RetryInfocontrols recoverable throttling delays; other retries use the existing 100 ms exponential base, with up to 100 ms of jitter.RequestErrorand FFI error classification, while retaining the gRPC code in the message..set_client_computed_stats()in the resource attributes and request metadata.How to test the change?
cargo check -p libdd-data-pipelinecargo +nightly-2026-07-26 fmt --all -- --checkcargo +stable clippy -p libdd-data-pipeline --all-targets --no-deps -- -D warningscargo +nightly clippy -p libdd-data-pipeline --test test_trace_exporter_otlp_grpc -- -D warningscargo +1.87.0 check -p libdd-data-pipeline --test test_trace_exporter_otlp_grpccargo nextest run -p libdd-data-pipeline -E '!test(tracing_integration_tests::)'(204 passed; 7 Docker-backed integration tests skipped locally)cargo test -p libdd-data-pipeline grpc --lib(34 passed)cargo test -p libdd-data-pipeline --test test_trace_exporter_otlp_grpc(2 passed)cargo test -p libdd-data-pipeline --doc(2 passed)cargo check -p libdd-data-pipeline --target wasm32-unknown-unknown --no-default-featurescargo ffi-test --skip-build --filter trace_exporter(1 passed; the full FFI build succeeded)cargo +stable clippy -p libdd-data-pipeline --all-targets -- -D warningscurrently stops on a pre-existingcollapsible_matchwarning inlibdd-trace-utils/src/tracer_payload.rs, which this PR does not modify.