Skip to content

feat(tracing): add DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT#3997

Draft
MilanGarnier wants to merge 23 commits into
masterfrom
MilanGarnier/propagation-behavior-extract
Draft

feat(tracing): add DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT#3997
MilanGarnier wants to merge 23 commits into
masterfrom
MilanGarnier/propagation-behavior-extract

Conversation

@MilanGarnier

Copy link
Copy Markdown
Contributor

Summary

Implements DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT (APMAPI-1941, feature-parity #353) for the PHP tracer, matching behavior already present in .NET, Python, Node, Java, Ruby, and Rust.

Three values:

  • continue (default): inherit upstream trace context unchanged — no behavior change
  • restart: start a fresh trace; the upstream context is captured as a span link with reason=propagation_behavior_extract
  • ignore: drop all extracted context including baggage and sampling priority

Design:

  • Single chokepoint: all extraction funnels through ddtrace_apply_distributed_tracing_result in distributed_tracing_headers.c, covering both request-init and consume_distributed_tracing_headers userland calls
  • restart path: when the root span doesn't yet exist at request-init time, the span link is queued in DDTRACE_G(pending_upstream_span_link) and consumed in ddtrace_open_span when the root span is created
  • Extracted ddtrace_build_span_link_from_result() from SpanLink::fromHeaders for reuse

Test plan

  • tests/ext/distributed_tracing/propagation_behavior_extract_continue.phpt — verifies trace_id inherited, no span link, baggage preserved
  • tests/ext/distributed_tracing/propagation_behavior_extract_restart.phpt — verifies fresh trace_id, span link with correct upstream ids and reason, baggage preserved, _dd.p.* not in link attributes
  • tests/ext/distributed_tracing/propagation_behavior_extract_ignore.phpt — verifies fresh trace_id, no span link, baggage dropped, sampling priority dropped
  • tests/ext/distributed_tracing/propagation_behavior_extract_config.phpt — verifies case-insensitive parsing, invalid value falls back to continue
  • CI phpt suite

Related

  • APMAPI-1941
  • Ruby: dd-trace-rb#5844
  • Rust: dd-trace-rs#248

🤖 Generated with Claude Code

@MilanGarnier MilanGarnier added the AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos label Jun 17, 2026
@datadog-official

datadog-official Bot commented Jun 17, 2026

Copy link
Copy Markdown

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 5 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-php | appsec integration tests: [test8.4-release]   View in Datadog   GitLab

🧪 1 Test failed

All test failures are known flaky.

❄️ Known flaky: extended heartbeat re-emits configuration, dependencies and integrations() from com.datadog.appsec.php.integration.TelemetryExtendedHeartbeatTests   View in Datadog
java.lang.AssertionError: phpredis not emitted via app-started/app-integrations-change; saw: []. Expression: (phpredis in flushed). Values: flushed = []

java.lang.AssertionError: phpredis not emitted via app-started/app-integrations-change; saw: []. Expression: (phpredis in flushed). Values: flushed = []
	at org.codehaus.groovy.runtime.InvokerHelper.createAssertError(InvokerHelper.java:416)
	at com.datadog.appsec.php.integration.TelemetryExtendedHeartbeatTests.extended heartbeat re-emits configuration, dependencies and integrations(TelemetryExtendedHeartbeatTests.groovy:70)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Not introduced in this PR.

DataDog/apm-reliability/dd-trace-php | test_extension_ci: [7.0]   View in Datadog   GitLab

DataDog/apm-reliability/dd-trace-php | test_extension_ci: [7.1]   View in Datadog   GitLab

View all 5 failed jobs.

ℹ️ Info

No other issues found (see more)

❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 54.08% (+0.00%)

Useful? React with 👍 / 👎

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

MilanGarnier and others added 5 commits June 17, 2026 17:11
Adds the new `DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT` config key (values:
continue, restart, ignore) with a CUSTOM(INT) parser, the corresponding
C enum, and the supported-configurations.json entry.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds three behaviors at the single extraction chokepoint
(ddtrace_apply_distributed_tracing_result):

- continue (default): inherit upstream trace context unchanged
- restart: start a fresh trace; upstream captured as a span link with
  reason=propagation_behavior_extract. When the root span doesn't exist
  yet at request-init time, the link is queued in
  DDTRACE_G(pending_upstream_span_link) and attached in ddtrace_open_span.
- ignore: drop all extracted context including baggage and sampling priority

Also extracts ddtrace_build_span_link_from_result() from the SpanLink
fromHeaders method so it can be reused by the restart path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers the three behaviors (continue, restart, ignore) and config
parsing (case-insensitive values, invalid value falls back to default).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@MilanGarnier MilanGarnier force-pushed the MilanGarnier/propagation-behavior-extract branch from 6b7e259 to 3ca8428 Compare June 17, 2026 15:33
Comment thread tracer/distributed_tracing_headers.c Outdated
Comment thread tracer/distributed_tracing_headers.c Outdated
Comment thread tracer/distributed_tracing_headers.c Outdated
Comment thread tracer/functions.c
@MilanGarnier MilanGarnier marked this pull request as ready for review June 23, 2026 12:15
@MilanGarnier MilanGarnier requested a review from a team as a code owner June 23, 2026 12: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: 19c7dafd9f

ℹ️ 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 tracer/distributed_tracing_headers.c Outdated
Comment on lines +646 to +647
zend_hash_clean(&result->meta_tags);
zend_hash_clean(&result->propagated_tags);

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 Drop upstream tracestate on restart

When DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=restart receives headers that include x-datadog-origin or W3C tracestate, this path only clears trace id/parent/sampling and _dd.p.*; the code below still moves result->origin, result->tracestate, and tracestate_unknown_dd_keys onto the new root/global context, and outbound injection later re-emits them. In that scenario the restarted trace continues propagating upstream trace context instead of preserving only baggage plus the span link.

Useful? React with 👍 / 👎.

@MilanGarnier MilanGarnier marked this pull request as draft June 29, 2026 11:41
@pr-commenter

pr-commenter Bot commented Jun 29, 2026

Copy link
Copy Markdown

Benchmarks [ tracer ]

Benchmark execution time: 2026-07-03 16:06:08

Comparing candidate commit 7cd5bf1 in PR branch MilanGarnier/propagation-behavior-extract with baseline commit d262f72 in branch master.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 194 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 ----------------------------------'

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

Labels

AI Generated Largely based on code generated by an AI or LLM. This label is the same across all dd-trace-* repos

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants