Skip to content

feat(tracing): add DD_TRACE_PROPAGATION_EXTRACT_FIRST - #356

Draft
MilanGarnier wants to merge 2 commits into
mainfrom
milan.garnier/propagation-extract-first
Draft

feat(tracing): add DD_TRACE_PROPAGATION_EXTRACT_FIRST#356
MilanGarnier wants to merge 2 commits into
mainfrom
milan.garnier/propagation-extract-first

Conversation

@MilanGarnier

@MilanGarnier MilanGarnier commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Description

Adds C++ support for DD_TRACE_PROPAGATION_EXTRACT_FIRST.
Existing documentation for the configuration : DD_TRACE_PROPAGATION_EXTRACT_FIRST in Feature Parity Dashboard

Motivation

Allow extraction to stop after the first successfully extracted trace context, matching the shared tracer configuration.

Additional Notes

Priority: low

  • Generated supported-configurations.json with config-inversion.
  • Unit tests cover configuration precedence, heterogeneous W3C tracestate handling, and fallback after an unsuccessful extractor.

Jira ticket: N/A

@pr-commenter

pr-commenter Bot commented Aug 19, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-08-26 13:10:45

Comparing candidate commit 984a97f in PR branch milan.garnier/propagation-extract-first with baseline commit 765983d in branch main.

Found 2 performance improvements and 3 performance regressions! Performance is the same for 3 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:BM_HexPadded_uint64/NoPadding

  • 🟥 execution_time [+2.318ns; +2.362ns] or [+4.429%; +4.513%]

scenario:BM_HexPadded_uint64/WorstCasePadding

  • 🟥 execution_time [+1.282ns; +1.373ns] or [+2.677%; +2.866%]

scenario:BM_Hex_uint64

  • 🟥 execution_time [+0.487ns; +0.510ns] or [+2.119%; +2.220%]

scenario:BM_TraceID_ParseHex/128bit

  • 🟩 execution_time [-49.662ns; -49.610ns] or [-28.753%; -28.723%]

scenario:BM_TraceID_ParseHex/64bit

  • 🟩 execution_time [-22.507ns; -22.491ns] or [-24.526%; -24.509%]

@datadog-datadog-prod-us1-2

This comment has been minimized.

@MilanGarnier MilanGarnier added AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos and removed AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos labels Aug 19, 2026
@MilanGarnier
MilanGarnier marked this pull request as ready for review August 26, 2026 09:16
@MilanGarnier
MilanGarnier requested review from a team as code owners August 26, 2026 09:16

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

ℹ️ 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 src/datadog/tracer.cpp Outdated
Comment on lines +325 to +326
if (propagation_extract_first_ && extracted_trace_context) {
break;

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 Validate context before stopping extraction

When DD_TRACE_PROPAGATION_EXTRACT_FIRST=true, an earlier style can return a trace ID without a usable parent ID or origin—for example, incomplete Datadog headers followed by a complete matching W3C traceparent. This condition stops immediately because it checks only trace_id, after which the validation below returns MISSING_PARENT_SPAN_ID instead of allowing the later style to supply a valid context. Stop only after the extracted context meets the validity requirements used below; otherwise continue trying configured styles.

Useful? React with 👍 / 👎.

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.

Indeed, we can see line 375 a test about parent_id.
I think we should clarify what is a successful extraction (and I suppose this would deserve a dedicated unit test).
Once again, I would really like to clarify the purpose of this block of code. I would start by extracting lines 277-343, but that's only a suggestion after a quick analysis, to be challenged.

@xlamorlette-datadog

Copy link
Copy Markdown
Collaborator

For the record: DD_TRACE_PROPAGATION_EXTRACT_FIRST in Feature Parity Dashboard.

@xlamorlette-datadog xlamorlette-datadog 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.

I find the C++ Tracer code difficult to reason because it is not in a very good state: it contains lot of legacy code, with questionable technical choices (but, unfortunately, many are part of the public interface).
From now on, I think we should try to clean the existing code to avoid deteriorating the situation further.
Especially here: Tracer::extract_span() is the biggest function: 273 lines!
Please, I think we should refactor this function (in a dedicated PR) before adding complexity to it.

Comment thread src/datadog/tracer.cpp
{extracted_tag});

if (!first_style_with_trace_id && data->trace_id.has_value()) {
const bool extracted_trace_context = data->trace_id.has_value();

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 the extracted_trace_context name is misleading:

  • It makes me think this variable is a trace context.
  • This only checks that a trace id was extracted, not a full context, which, I think, relates to the comment from Codex below.

Actually, because the existing code is not clean, I find it very difficult to reason about this:

  • The data name does not convey any useful meaning.
  • The on-going modification is only about a part of the huge (270 lines!) Tracer::extract_span() function.

I suggest adding a dedicated refactoring PR before this one to clean the Tracer::extract_span() function:

  • At least extract the part to be modified, to clarify its purpose, and improve variable names. This could also allow to unit test easier the new behavior.
  • Ideally, split the function in big blocks (skimming the function, it seems to me there are at least 4 different blocks).

Comment thread src/datadog/tracer.cpp Outdated
Comment on lines +325 to +326
if (propagation_extract_first_ && extracted_trace_context) {
break;

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.

Indeed, we can see line 375 a test about parent_id.
I think we should clarify what is a successful extraction (and I suppose this would deserve a dedicated unit test).
Once again, I would really like to clarify the purpose of this block of code. I would start by extracting lines 277-343, but that's only a suggestion after a quick analysis, to be challenged.

Comment thread test/test_tracer.cpp
std::vector<PropagationStyle> injection_styles;
std::unordered_map<std::string, std::string> extracted_headers;
std::unordered_map<std::string, std::string> expected_injected_headers;
bool extract_first = false;

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 should be added in the capture block (lines 2121-2126).

@MilanGarnier
MilanGarnier marked this pull request as draft August 26, 2026 13:23
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