feat(tracing): propagate trace context into Temporal via OTel interceptor#467
Open
NiteshDhanpal wants to merge 1 commit into
Open
feat(tracing): propagate trace context into Temporal via OTel interceptor#467NiteshDhanpal wants to merge 1 commit into
NiteshDhanpal wants to merge 1 commit into
Conversation
…ptor
Attach temporalio.contrib.opentelemetry.TracingInterceptor to the Temporal
client (both get_temporal_client entrypoints) when an OTel observability mode
is active (SGP_OBS_MODE in {dual, lgtm}). This threads the caller's W3C trace
context across the workflow -> activity boundary, so business spans created
inside the model-loop activity see an active observability context and can be
tagged with its trace_id via obs_correlation().
Gated + lazy-imported: default dd_only mode adds nothing and the temporalio
OTel contrib is only imported when needed, so this is a no-op unless opted in.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
NiteshDhanpal
force-pushed
the
obs/02-fastacp-w3c-ingress
branch
from
July 21, 2026 20:46
2bfde1c to
24f0835
Compare
NiteshDhanpal
force-pushed
the
obs/03-temporal-otel-interceptor
branch
from
July 21, 2026 20:46
78738ee to
cbcd20a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack (3/3)
What this PR does
Attaches
temporalio.contrib.opentelemetry.TracingInterceptorto the Temporal client (bothget_temporal_cliententrypoints —workers/worker.pyandclients/temporal/utils.py) when an OTel observability mode is active (SGP_OBS_MODEin{dual, lgtm}).This threads the caller's W3C trace context (established at ingress in PR 2) across the workflow → activity boundary, so business spans created inside the model-loop activity see an active observability context and get tagged with its
trace_idviaobs_correlation()(PR 1).Why it's needed
The agent model loop runs in Temporal activities. Without context propagation there is no active obs context inside the activity, so
obs_correlation()would return{}for the very spans we most want to correlate (invoke_agent / plan / execute_tool / chat).Safety
Gated on
SGP_OBS_MODE in {dual, lgtm}and lazy-imported — the defaultdd_onlymode adds no interceptor, so this is a no-op unless opted in.Verification
py_compile+ unit smoke on both entrypoints: empty indd_only/unset,[TracingInterceptor]indual.Not in this stack (follow-ups)
egp-api-backendside (app-graph collector +CustomJSONFormatterunifiedtrace_id) — tracked separately.Greptile Summary
This PR attaches
TracingInterceptorfromtemporalio.contrib.opentelemetryto both Temporal client entrypoints (clients/temporal/utils.pyandtemporal/workers/worker.py) so W3C trace context established at FastACP ingress propagates into scheduled workflow calls. The change is gated onSGP_OBS_MODE in {dual, lgtm}with a lazy import and ImportError fallback, making it a no-op in the defaultdd_onlymode._build_otel_interceptors()helper that conditionally returns a[TracingInterceptor()]list and is wired intoconnect_kwargs[\"interceptors\"]beforeClient.connect().Workerconstructor inAgentexWorker.run()still receives onlyself.interceptors— it does not include the OTel interceptors, so trace context will not be extracted during inbound activity execution (see previously raised issue).Confidence Score: 4/5
Safe to merge for the client-side path; the worker-side activity context extraction remains broken until the OTel interceptors are also merged into the Worker constructor.
The _build_otel_interceptors() result is wired into Client.connect() in both entrypoints, correctly propagating trace context for outbound workflow scheduling. However, AgentexWorker.run() builds Worker(interceptors=self.interceptors) without including the OTel interceptors, so the TracingInterceptor is never registered on the worker side. Trace context from incoming workflow execution headers will not be extracted into activities, meaning obs_correlation() inside the model-loop activity will still return {} — the core goal stated in the PR description is not yet achieved.
src/agentex/lib/core/temporal/workers/worker.py — specifically the Worker construction in AgentexWorker.run() which needs to merge _build_otel_interceptors() output with self.interceptors.
Important Files Changed
Comments Outside Diff (1)
src/agentex/lib/core/temporal/workers/worker.py, line 228-255 (link)_build_otel_interceptors()runs insideget_temporal_client()and setsconnect_kwargs["interceptors"], which lands onClient.connect(). That covers outbound calls from the client (e.g. scheduling a workflow). However, for the W3C context to be extracted and made active during activity execution,TracingInterceptormust also be passed to theWorkerconstructor. The currentWorker(interceptors=self.interceptors)receives only user-provided interceptors — not the OTel ones — soobs_correlation()inside activities will still see an empty context, defeating the stated goal of this PR.A fix requires
_build_otel_interceptors()to be called inAgentexWorker.run()(in addition to insideget_temporal_client()), and its result merged into theWorker'sinterceptorsargument alongsideself.interceptors.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (2): Last reviewed commit: "feat(tracing): propagate trace context i..." | Re-trigger Greptile