mirror of
https://github.com/openai/codex.git
synced 2026-11-08 16:38:30 +00:00
feat(app-server): propagate app-server trace context into core (#13368)
### Summary Propagate trace context originating at app-server RPC method handlers -> codex core submission loop (so this includes spans such as `run_turn`!). This implements PR 2 of the app-server tracing rollout. This also removes the old lower-level env-based reparenting in core so explicit request/submission ancestry wins instead of being overridden by ambient `TRACEPARENT` state. ### What changed - Added `trace: Option<W3cTraceContext>` to codex_protocol::Submission - Taught `Codex::submit()` / `submit_with_id()` to automatically capture the current span context when constructing or forwarding a submission - Wrapped the core submission loop in a submission_dispatch span parented from Submission.trace - Warn on invalid submission trace carriers and ignore them cleanly - Removed the old env-based downstream reparenting path in core task execution - Stopped OTEL provider init from implicitly attaching env trace context process-wide - Updated mcp-server Submission call sites for the new field Added focused unit tests for: - capturing trace context into Submission - preferring `Submission.trace` when building the core dispatch span ### Why PR 1 gave us consistent inbound request spans in app-server, but that only covered the transport boundary. For long-running work like turns and reviews, the important missing piece was preserving ancestry after the request handler returns and core continues work on a different async path. This change makes that handoff explicit and keeps the parentage rules simple: - app-server request span sets the current context - `Submission.trace` snapshots that context - core restores it once, at the submission boundary - deeper core spans inherit naturally That also lets us stop relying on env-based reparenting for this path, which was too ambient and could override explicit ancestry.
This commit is contained in:
1 parent
0fbd84081b
commit
52521a5e40
12 files changed
+489
-196
No files matched your search
@@ -7,7 +7,6 @@ use crate::trace_context::context_from_trace_headers;
|
||||
use gethostname::gethostname;
|
||||
use opentelemetry::Context;
|
||||
use opentelemetry::KeyValue;
|
||||
use opentelemetry::context::ContextGuard;
|
||||
use opentelemetry::global;
|
||||
use opentelemetry::trace::TracerProvider as _;
|
||||
use opentelemetry_appender_tracing::layer::OpenTelemetryTracingBridge;
|
||||
@@ -28,7 +27,6 @@ use opentelemetry_sdk::trace::BatchSpanProcessor;
|
||||
use opentelemetry_sdk::trace::SdkTracerProvider;
|
||||
use opentelemetry_sdk::trace::Tracer;
|
||||
use opentelemetry_semantic_conventions as semconv;
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::sync::OnceLock;
|
||||
@@ -43,10 +41,6 @@ const HOST_NAME_ATTRIBUTE: &str = "host.name";
|
||||
const TRACEPARENT_ENV_VAR: &str = "TRACEPARENT";
|
||||
const TRACESTATE_ENV_VAR: &str = "TRACESTATE";
|
||||
static TRACEPARENT_CONTEXT: OnceLock<Option<Context>> = OnceLock::new();
|
||||
|
||||
thread_local! {
|
||||
static TRACEPARENT_GUARD: RefCell<Option<ContextGuard>> = const { RefCell::new(None) };
|
||||
}
|
||||
pub struct OtelProvider {
|
||||
pub logger: Option<SdkLoggerProvider>,
|
||||
pub tracer_provider: Option<SdkTracerProvider>,
|
||||
@@ -113,10 +107,6 @@ impl OtelProvider {
|
||||
global::set_tracer_provider(provider);
|
||||
global::set_text_map_propagator(TraceContextPropagator::new());
|
||||
}
|
||||
if tracer.is_some() {
|
||||
attach_traceparent_context();
|
||||
}
|
||||
|
||||
Ok(Some(Self {
|
||||
logger,
|
||||
tracer_provider,
|
||||
@@ -176,18 +166,6 @@ pub fn traceparent_context_from_env() -> Option<Context> {
|
||||
.clone()
|
||||
}
|
||||
|
||||
fn attach_traceparent_context() {
|
||||
TRACEPARENT_GUARD.with(|guard| {
|
||||
let mut guard = guard.borrow_mut();
|
||||
if guard.is_some() {
|
||||
return;
|
||||
}
|
||||
if let Some(context) = traceparent_context_from_env() {
|
||||
*guard = Some(context.attach());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn load_traceparent_context() -> Option<Context> {
|
||||
let traceparent = env::var(TRACEPARENT_ENV_VAR).ok()?;
|
||||
let tracestate = env::var(TRACESTATE_ENV_VAR).ok();
|
||||
|
||||
@@ -15,7 +15,6 @@ use crate::metrics::names::WEBSOCKET_EVENT_COUNT_METRIC;
|
||||
use crate::metrics::names::WEBSOCKET_EVENT_DURATION_METRIC;
|
||||
use crate::metrics::names::WEBSOCKET_REQUEST_COUNT_METRIC;
|
||||
use crate::metrics::names::WEBSOCKET_REQUEST_DURATION_METRIC;
|
||||
use crate::otel_provider::traceparent_context_from_env;
|
||||
use crate::sanitize_metric_tag_value;
|
||||
use chrono::SecondsFormat;
|
||||
use chrono::Utc;
|
||||
@@ -41,7 +40,6 @@ use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
use tokio::time::error::Elapsed;
|
||||
use tracing::Span;
|
||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||
|
||||
pub use crate::OtelEventMetadata;
|
||||
pub use crate::OtelManager;
|
||||
@@ -92,12 +90,6 @@ impl OtelManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_traceparent_parent(&self, span: &Span) {
|
||||
if let Some(context) = traceparent_context_from_env() {
|
||||
let _ = span.set_parent(context);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn record_responses(&self, handle_responses_span: &Span, event: &ResponseEvent) {
|
||||
handle_responses_span.record("otel.name", OtelManager::responses_type(event));
|
||||
|
||||
|
||||
Reference in new issue
Block a user