feat(otel): Parent Workflow span onto shared execution trace - #647
feat(otel): Parent Workflow span onto shared execution trace#647ayushiahjolia wants to merge 1 commit into
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
5c0f1a8 to
95fb7cd
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
95fb7cd to
d97ef9c
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
d97ef9c to
6896e3d
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
8a88e75 to
40ee121
Compare
This comment has been minimized.
This comment has been minimized.
40ee121 to
f941656
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| return deferredDecisions.computeIfAbsent( | ||
| intent.deferredTraceId(), | ||
| key -> delegate.shouldSample(Context.root(), key, name, spanKind, attributes, Collections.emptyList())); |
There was a problem hiding this comment.
Codex AI review
[P2] Re-evaluate deferred sampling per invocation. This provider-lifetime cache is keyed only by trace ID, so later reinvocations never consult a stateful, rate-limited, or remotely updated agent sampler. The first decision persists until eviction, contrary to the documented once-per-invocation behavior. Carry a unique invocation key alongside the canonical trace ID and cache by that key; add a two-invocation test verifying the delegate is called once for each invocation.
Codex AI reviewFound one deferred-sampling lifecycle bug. Tests do not cover sampler reevaluation across reinvocations. Reviewed commit |
Claude AI reviewNo actionable findings. I reviewed the complete SHA-anchored diff ( The change reparents the Workflow span onto a shared execution ancestor (remote backend parent when a valid
Test coverage is thorough and satisfies the AGENTS.md test requirement (sampling precedence, Residual test risk (could not be verified under read-only, no-build inspection):
Reviewed commit |
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Issue Link, if available
#644
Description
After this change,
Trace ID is derived from the backend's _X_AMZN_TRACE_ID Root when valid, otherwise from the execution ARN - stable across reinvocations.
Workflow span parents onto the reconstructed remote backend parent (from _X_AMZN_TRACE_ID Parent), or the synthetic execution root when no valid Parent exists. Invocation span additionally prefers the current same-trace ambient span (Span.current()) when one exists, falling back to the same ancestor as the Workflow span.
Sampling is decided once per invocation with this precedence: explicit backend Sampled=0/1 → same-trace ambient span's decision → customer's configured sampler (evaluated once). The decision is applied to all durable spans; the sampler is not re-invoked per span.
Cross-invocation consistency comes from the inputs being stable (trace ID, upstream Sampled), so deterministic samplers reach the same decision every reinvocation without sharing state across processes.
Note that when auto-instrumentation (e.g. ADOT) is active, the Lambda runtime updates _X_AMZN_TRACE_ID Parent to point at the agent's handler span - which is the same span as the ambient Span.current(). So in practice both the Workflow and Invocation spans parent onto that same agent span; they simply reach it through different channels (the header vs. the live context API). The two paths diverge only when no ambient span is active (no auto-instrumentation): the Workflow span still uses the header's Parent, while the Invocation span falls back to the ancestor.
The Workflow span is created every invocation with a deterministic span ID but is exported only from the terminal invocation - earlier invocations' copies are left un-ended and discarded. Because each invocation parents its Workflow span onto that invocation's own ambient span (the _X_AMZN_TRACE_ID Parent), the single exported Workflow span carries the last invocation's ambient span as its parent.
Demo/Screenshots
N/A
Checklist
Testing
Unit Tests
Have unit tests been written for these changes? Updated.
Integration Tests
Have integration tests been written for these changes? Added/Updated
Examples
Has a new example been added for the change? (if applicable) N/A