Skip to content

feat(propagation): emit and forward OTel consistent-probability ot tracestate member - #283

Open
MilanGarnier wants to merge 7 commits into
mainfrom
milan.garnier/otel-tracestate-ot-th
Open

feat(propagation): emit and forward OTel consistent-probability ot tracestate member#283
MilanGarnier wants to merge 7 commits into
mainfrom
milan.garnier/otel-tracestate-ot-th

Conversation

@MilanGarnier

Copy link
Copy Markdown
Contributor

Summary

  • Parse the inbound ot tracestate member (rv/th) and forward it raw, rewriting only on injection
  • Emit rv/th on inject based on the sampling decision, keeping unrecognized ot sub-keys
  • Thread the ot decision from sampler through to the inject context

Test plan

  • cargo test -p datadog-opentelemetry
  • cargo clippy --all-targets -- -D warnings

@MilanGarnier
MilanGarnier marked this pull request as ready for review August 3, 2026 11:15
@MilanGarnier
MilanGarnier requested a review from a team as a code owner August 3, 2026 11:15

@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: 4b2b50fa3d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Cargo.toml
# TraceRootSamplingInfo::otel_consistent_sampling) is only on this
# libdatadog branch until libdd-sampling is released.
[patch.crates-io]
libdd-sampling = { git = "https://github.com/DataDog/libdatadog", branch = "milan.garnier/otel-consistent-sampling" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Replace the dev-only libdd-sampling patch

The added patch replaces the crates.io libdd-sampling with a git branch that the comment itself marks as dev-only. Clean builds and publishing now depend on fetching that mutable branch instead of a released crate; in registry-only/offline or restricted-network environments, cargo check --locked fails before compilation because Cargo tries to update https://github.com/DataDog/libdatadog. Please wait for/bump to the released libdd-sampling version and remove this patch, including the duplicate instrumentation workspace patch.

Useful? React with 👍 / 👎.

Comment thread datadog-opentelemetry/src/propagation/tracecontext.rs
Comment thread datadog-opentelemetry/src/sampler.rs Outdated
inbound: Option<String>,
) -> Option<String> {
match (is_local_root, derived) {
(true, Some(ocs)) => ot_set_rv_th(inbound.as_deref(), Some(ocs.rv), Some(ocs.th)),

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 Keep inherited rv when resampling deferred parents

For a deferred remote parent (for example Datadog/B3 extracted without a sampling priority while W3C tracestate supplied ot=rv:...), inbound_ot reaches this probability branch, but the code replaces the inherited explicit randomness with ocs.rv derived from the trace id. OpenTelemetry uses rv as the stable randomness source for the trace, so changing it on the child can make downstream services compare a different R value and produce inconsistent keep/drop decisions; keep the inbound rv when present and only update th.

Useful? React with 👍 / 👎.

Comment thread datadog-opentelemetry/src/propagation/tracecontext.rs Outdated
Comment on lines +151 to +154
let ot = propagation_data.ot.take().or_else(|| {
cx.get::<DatadogExtractData>()
.and_then(|extract_data| extract_data.ot.clone())
});

@iunanua iunanua Aug 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.

It seems the fallback could resurrect an erased ot:

get_trace_propagation_data returns EMPTY_PROPAGATION_DATA when the trace isn't registered, so ot: None is indistinguishable from "the local root resolved this to None on purpose":

  • inbound traceparent + deferred dd= + ot=th:e6666666666666 (no rv)
  • local root's decision is non-probability - e.g. the rate limiter fired, which makes otel_consistent_sampling() return None via rl_effective_rate.is_some() (not a corner case)
  • resolve_outbound_ot(true, None, Some("th:e666...")) > ot_extract_rv > None, ot_set_rv_th filters the th out, no other subkeys > registry stores ot: None
  • inject falls back to DatadogExtractData and emits ot=th:e6666666666666

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants