-
Notifications
You must be signed in to change notification settings - Fork 182
feat(tracing): add DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT #3997
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
0ca6b04
5a63578
6914d02
68ddc93
3ca8428
f5db737
6374dad
602e2be
a39e0a4
cb5cc57
c7674bd
fa54461
5d0fc77
ea4bf80
5832c73
19c7daf
2bca52d
3a09adc
7e17c78
57a6961
a25a0dd
da401ba
7cd5bf1
6888589
a087da7
c0fae48
e53c3ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -184,8 +184,13 @@ public function startSpan(): SpanInterface | |
| $parentSpan = Span::fromContext($parentContext); | ||
| $parentSpanContext = $parentSpan->getContext(); | ||
|
|
||
| $span = $parentSpanContext->isValid() ? null : \DDTrace\start_trace_span($this->startEpochNanos); | ||
| $traceId = $parentSpanContext->isValid() ? $parentSpanContext->getTraceId() : \DDTrace\root_span()->traceId; | ||
| $behaviorExtract = \dd_trace_env_config('DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT'); | ||
| $restartOrIgnore = $parentSpanContext->isValid() && ($behaviorExtract === 1 || $behaviorExtract === 2); | ||
|
|
||
| $span = ($parentSpanContext->isValid() && !$restartOrIgnore) ? null : \DDTrace\start_trace_span($this->startEpochNanos); | ||
| $traceId = ($parentSpanContext->isValid() && !$restartOrIgnore) | ||
| ? $parentSpanContext->getTraceId() | ||
| : \DDTrace\root_span()->traceId; | ||
|
|
||
| $samplingResult = $this | ||
| ->tracerSharedState | ||
|
|
@@ -205,7 +210,7 @@ public function startSpan(): SpanInterface | |
| $sampled = SamplingResult::RECORD_AND_SAMPLE === $samplingDecision; | ||
| $samplingResultTraceState = $samplingResult->getTraceState(); | ||
|
|
||
| if ($parentSpanContext->isValid()) { | ||
| if ($parentSpanContext->isValid() && !$restartOrIgnore) { | ||
| // Traceparent: {2:version}-{32:hex trace id}-{16:hex parent id}-{2:trace_flags}, version always being '00' | ||
| // Since parentSpanContext is valid, the trace identifiers are guaranteed to be in hexadecimal format | ||
| $parentId = $parentSpanContext->getSpanId(); | ||
|
|
@@ -215,6 +220,14 @@ public function startSpan(): SpanInterface | |
| 'traceparent' => $traceParent, | ||
| 'tracestate' => (string) $samplingResultTraceState, // __toString() is implemented in TraceState | ||
| ]); | ||
| } elseif ($parentSpanContext->isValid() && $behaviorExtract === 1) { | ||
| // RESTART: pass upstream W3C context so C code creates a span link and starts fresh trace | ||
| $parentId = $parentSpanContext->getSpanId(); | ||
| $traceParent = "00-{$parentSpanContext->getTraceId()}-$parentId-01"; | ||
| \DDTrace\consume_distributed_tracing_headers([ | ||
| 'traceparent' => $traceParent, | ||
| 'tracestate' => (string) $samplingResultTraceState, | ||
|
Comment on lines
+226
to
+229
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When restart is triggered from an extracted OTel W3C context that carries tracestate or an unsampled trace flag, this synthetic header hard-codes sampled ( Useful? React with 👍 / 👎. |
||
| ]); | ||
| } elseif ($samplingResultTraceState) { | ||
| $samplingResultTraceState = $samplingResultTraceState->without('dd'); | ||
| \DDTrace\root_span()->tracestate = (string) $samplingResultTraceState; | ||
|
|
@@ -234,10 +247,13 @@ public function startSpan(): SpanInterface | |
| $this->attributes[$key] = $value; | ||
| } | ||
|
|
||
| $parentSpanContextBaggage = $parentContext->get(ContextKeys::baggage()); | ||
| if ($parentSpanContextBaggage) { | ||
| foreach($parentSpanContextBaggage->getAll() as $baggageKey => $baggageEntry) { | ||
| $span->baggage[$baggageKey] = $baggageEntry->getValue(); | ||
| if ($behaviorExtract !== 2) { | ||
| // `restart` or `continue` : propagate baggage | ||
| $parentSpanContextBaggage = $parentContext->get(ContextKeys::baggage()); | ||
| if ($parentSpanContextBaggage) { | ||
| foreach ($parentSpanContextBaggage->getAll() as $baggageKey => $baggageEntry) { | ||
| $span->baggage[$baggageKey] = $baggageEntry->getValue(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -249,7 +265,7 @@ public function startSpan(): SpanInterface | |
| $parentSpan, | ||
| $parentContext, | ||
| $this->tracerSharedState->getSpanProcessor(), | ||
| $parentSpanContext->isValid() ? ResourceInfoFactory::emptyResource() : $this->tracerSharedState->getResource(), | ||
| ($parentSpanContext->isValid() && !$restartOrIgnore) ? ResourceInfoFactory::emptyResource() : $this->tracerSharedState->getResource(), | ||
| $this->attributes, | ||
| $this->links, | ||
| $this->totalNumberOfLinksAdded, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| --TEST-- | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT: invalid value falls back to continue | ||
| --ENV-- | ||
| DD_TRACE_GENERATE_ROOT_SPAN=0 | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=invalid_value | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| DDTrace\consume_distributed_tracing_headers([ | ||
| "x-datadog-trace-id" => 42, | ||
| "x-datadog-parent-id" => 10, | ||
| ]); | ||
|
|
||
| $span = DDTrace\start_span(); | ||
| $root = DDTrace\root_span(); | ||
|
|
||
| // invalid value falls back to default (continue): inherits upstream trace id | ||
| echo "same_as_upstream: " . ($root->traceId === "0000000000000000000000000000002a" ? "yes" : "no") . "\n"; | ||
|
|
||
| DDTrace\close_span(); | ||
| ?> | ||
| --EXPECT-- | ||
| same_as_upstream: yes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| --TEST-- | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT: Ignore (mixed case) is accepted | ||
| --ENV-- | ||
| DD_TRACE_GENERATE_ROOT_SPAN=0 | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=Ignore | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| DDTrace\consume_distributed_tracing_headers([ | ||
| "x-datadog-trace-id" => 42, | ||
| "x-datadog-parent-id" => 10, | ||
| ]); | ||
|
|
||
| $span = DDTrace\start_span(); | ||
| $root = DDTrace\root_span(); | ||
|
|
||
| echo "same_as_upstream: " . ($root->traceId === "0000000000000000000000000000002a" ? "yes" : "no") . "\n"; | ||
| echo "links_count: " . count($root->links) . "\n"; | ||
|
|
||
| DDTrace\close_span(); | ||
| ?> | ||
| --EXPECT-- | ||
| same_as_upstream: no | ||
| links_count: 0 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| --TEST-- | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT: CONTINUE (uppercase) is accepted | ||
| --ENV-- | ||
| DD_TRACE_GENERATE_ROOT_SPAN=0 | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=CONTINUE | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| DDTrace\consume_distributed_tracing_headers([ | ||
| "x-datadog-trace-id" => 42, | ||
| "x-datadog-parent-id" => 10, | ||
| ]); | ||
|
|
||
| $span = DDTrace\start_span(); | ||
| $root = DDTrace\root_span(); | ||
|
|
||
| echo "same_as_upstream: " . ($root->traceId === "0000000000000000000000000000002a" ? "yes" : "no") . "\n"; | ||
|
|
||
| DDTrace\close_span(); | ||
| ?> | ||
| --EXPECT-- | ||
| same_as_upstream: yes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| --TEST-- | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT: RESTART (uppercase) is accepted | ||
| --ENV-- | ||
| DD_TRACE_GENERATE_ROOT_SPAN=0 | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=RESTART | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| DDTrace\consume_distributed_tracing_headers([ | ||
| "x-datadog-trace-id" => 42, | ||
| "x-datadog-parent-id" => 10, | ||
| ]); | ||
|
|
||
| $span = DDTrace\start_span(); | ||
| $root = DDTrace\root_span(); | ||
|
|
||
| echo "same_as_upstream: " . ($root->traceId === "0000000000000000000000000000002a" ? "yes" : "no") . "\n"; | ||
| echo "links_count: " . count($root->links) . "\n"; | ||
|
|
||
| DDTrace\close_span(); | ||
| ?> | ||
| --EXPECT-- | ||
| same_as_upstream: no | ||
| links_count: 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| --TEST-- | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=continue inherits upstream context | ||
| --ENV-- | ||
| DD_TRACE_GENERATE_ROOT_SPAN=0 | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=continue | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| DDTrace\consume_distributed_tracing_headers([ | ||
| "x-datadog-trace-id" => 42, | ||
| "x-datadog-parent-id" => 10, | ||
| "x-datadog-sampling-priority" => 1, | ||
| "baggage" => "user.id=123", | ||
| ]); | ||
|
|
||
| $span = DDTrace\start_span(); | ||
| $root = DDTrace\root_span(); | ||
|
|
||
| echo "trace_id: " . $root->traceId . "\n"; | ||
| echo "parent_id: " . $root->parentId . "\n"; | ||
| echo "links_count: " . count($root->links) . "\n"; | ||
|
|
||
| $headers = DDTrace\generate_distributed_tracing_headers(['baggage']); | ||
| echo "baggage: " . ($headers['baggage'] ?? 'none') . "\n"; | ||
|
|
||
| DDTrace\close_span(); | ||
| ?> | ||
| --EXPECT-- | ||
| trace_id: 0000000000000000000000000000002a | ||
| parent_id: 10 | ||
| links_count: 0 | ||
| baggage: user.id=123 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| --TEST-- | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=ignore drops all incoming context including baggage | ||
| --ENV-- | ||
| DD_TRACE_GENERATE_ROOT_SPAN=0 | ||
| DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=ignore | ||
| --FILE-- | ||
| <?php | ||
|
|
||
| DDTrace\consume_distributed_tracing_headers([ | ||
| "x-datadog-trace-id" => 42, | ||
| "x-datadog-parent-id" => 10, | ||
| "x-datadog-sampling-priority" => 2, | ||
| "x-datadog-tags" => "_dd.p.dm=-4", | ||
| "baggage" => "user.id=123", | ||
| ]); | ||
|
|
||
| $span = DDTrace\start_span(); | ||
| $root = DDTrace\root_span(); | ||
|
|
||
| // fresh trace: not from upstream | ||
| echo "same_as_upstream: " . ($root->traceId === "0000000000000000000000000000002a" ? "yes" : "no") . "\n"; | ||
| echo "parent_id: " . ($root->parentId ?? 0) . "\n"; | ||
|
|
||
| // no span link (context discarded entirely) | ||
| echo "links_count: " . count($root->links) . "\n"; | ||
|
|
||
| // baggage dropped | ||
| $headers = DDTrace\generate_distributed_tracing_headers(['baggage']); | ||
| echo "baggage: " . ($headers['baggage'] ?? 'none') . "\n"; | ||
|
|
||
| DDTrace\close_span(); | ||
| ?> | ||
| --EXPECT-- | ||
| same_as_upstream: no | ||
| parent_id: 0 | ||
| links_count: 0 | ||
| baggage: none |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With
DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT=restartorignore, this treats every valid OTel parent as extracted context. For ordinary in-process OTel children whose parent span is local, line 190 starts a new trace (and the restart branch can add a span link to the local parent) instead of preserving the parent/child relationship; the extract behavior should only apply when the parent context is remote/extracted, not for local spans created later in the same trace.Useful? React with 👍 / 👎.