From 33053c226fea33bee6942bad0754c08d04653ad3 Mon Sep 17 00:00:00 2001 From: Brian Strauch Date: Mon, 15 Jun 2026 12:17:42 -0700 Subject: [PATCH] Propagate OTEL trace id across client-workflow boundary The OTEL-aware OpenAI Agents interceptor propagated and seeded the OTEL span id but never the trace id, so the client-side root span and the workflow's reconstructed spans ended up in different traces. This made test_sdk_trace_to_otel_span_parenting flaky. Wire up the existing seed_trace_id so the workflow's root span reuses the caller's trace id. --- .../contrib/openai_agents/_otel_trace_interceptor.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/temporalio/contrib/openai_agents/_otel_trace_interceptor.py b/temporalio/contrib/openai_agents/_otel_trace_interceptor.py index 6b7bb3c1b..63f8f9d83 100644 --- a/temporalio/contrib/openai_agents/_otel_trace_interceptor.py +++ b/temporalio/contrib/openai_agents/_otel_trace_interceptor.py @@ -45,10 +45,11 @@ def header_contents(self) -> dict[str, Any]: otel_span = opentelemetry.trace.get_current_span() if otel_span and otel_span.get_span_context().is_valid: - otel_span_id = otel_span.get_span_context().span_id + span_context = otel_span.get_span_context() return { **super().header_contents(), - "otelSpanId": otel_span_id, + "otelSpanId": span_context.span_id, + "otelTraceId": span_context.trace_id, } else: return super().header_contents() @@ -63,6 +64,12 @@ def context_from_header( if span_info is None: return otel_span_id = span_info.get("otelSpanId") + otel_trace_id = span_info.get("otelTraceId") + + # Seed the trace id before the trace is reconstructed so the workflow's root + # OTEL span shares the caller's trace id rather than generating a new one. + if otel_trace_id and self._otel_id_generator: + self._otel_id_generator.seed_trace_id(otel_trace_id) # If only a trace was propagated from the caller, we need to seed for trace context if otel_span_id and self._otel_id_generator and span_info.get("spanId") is None: