mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat(core, tracing): create turn spans over websockets (#14632)
## Description Dependent on: - [responsesapi] https://github.com/openai/openai/pull/760991 - [codex-backend] https://github.com/openai/openai/pull/760985 `codex app-server -> codex-backend -> responsesapi` now reuses a persistent websocket connection across many turns. This PR updates tracing when using websockets so that each `response.create` websocket request propagates the current tracing context, so we can get a holistic end-to-end trace for each turn. Tracing is propagated via special keys (`ws_request_header_traceparent`, `ws_request_header_tracestate`) set in the `client_metadata` param in Responses API. Currently tracing on websockets is a bit broken because we only set tracing context on ws connection time, so it's detached from a `turn/start` request.
This commit is contained in:
@@ -72,15 +72,13 @@ use codex_protocol::protocol::ConversationAudioParams;
|
||||
use codex_protocol::protocol::RealtimeAudioFrame;
|
||||
use codex_protocol::protocol::Submission;
|
||||
use codex_protocol::protocol::W3cTraceContext;
|
||||
use core_test_support::tracing::install_test_tracing;
|
||||
use opentelemetry::trace::TraceContextExt;
|
||||
use opentelemetry::trace::TraceId;
|
||||
use opentelemetry::trace::TracerProvider as _;
|
||||
use opentelemetry_sdk::trace::SdkTracerProvider;
|
||||
use std::path::Path;
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
use tracing_opentelemetry::OpenTelemetrySpanExt;
|
||||
use tracing_subscriber::prelude::*;
|
||||
|
||||
use codex_protocol::mcp::CallToolResult as McpCallToolResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -90,7 +88,6 @@ use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Once;
|
||||
use std::time::Duration as StdDuration;
|
||||
|
||||
#[path = "codex_tests_guardian.rs"]
|
||||
@@ -2031,18 +2028,6 @@ fn text_block(s: &str) -> serde_json::Value {
|
||||
})
|
||||
}
|
||||
|
||||
fn init_test_tracing() {
|
||||
static INIT: Once = Once::new();
|
||||
INIT.call_once(|| {
|
||||
let provider = SdkTracerProvider::builder().build();
|
||||
let tracer = provider.tracer("codex-core-tests");
|
||||
let subscriber =
|
||||
tracing_subscriber::registry().with(tracing_opentelemetry::layer().with_tracer(tracer));
|
||||
tracing::subscriber::set_global_default(subscriber)
|
||||
.expect("global tracing subscriber should only be installed once");
|
||||
});
|
||||
}
|
||||
|
||||
async fn build_test_config(codex_home: &Path) -> Config {
|
||||
ConfigBuilder::default()
|
||||
.codex_home(codex_home.to_path_buf())
|
||||
@@ -2730,7 +2715,7 @@ async fn submit_with_id_captures_current_span_trace_context() {
|
||||
session_loop_termination: completed_session_loop_termination(),
|
||||
};
|
||||
|
||||
init_test_tracing();
|
||||
let _trace_test_context = install_test_tracing("codex-core-tests");
|
||||
|
||||
let request_parent = W3cTraceContext {
|
||||
traceparent: Some("00-00000000000000000000000000000011-0000000000000022-01".into()),
|
||||
@@ -2766,7 +2751,7 @@ async fn submit_with_id_captures_current_span_trace_context() {
|
||||
async fn new_default_turn_captures_current_span_trace_id() {
|
||||
let (session, _turn_context) = make_session_and_context().await;
|
||||
|
||||
init_test_tracing();
|
||||
let _trace_test_context = install_test_tracing("codex-core-tests");
|
||||
|
||||
let request_parent = W3cTraceContext {
|
||||
traceparent: Some("00-00000000000000000000000000000011-0000000000000022-01".into()),
|
||||
@@ -2801,7 +2786,7 @@ async fn new_default_turn_captures_current_span_trace_id() {
|
||||
|
||||
#[test]
|
||||
fn submission_dispatch_span_prefers_submission_trace_context() {
|
||||
init_test_tracing();
|
||||
let _trace_test_context = install_test_tracing("codex-core-tests");
|
||||
|
||||
let ambient_parent = W3cTraceContext {
|
||||
traceparent: Some("00-00000000000000000000000000000033-0000000000000044-01".into()),
|
||||
@@ -2834,7 +2819,7 @@ fn submission_dispatch_span_prefers_submission_trace_context() {
|
||||
|
||||
#[test]
|
||||
fn submission_dispatch_span_uses_debug_for_realtime_audio() {
|
||||
init_test_tracing();
|
||||
let _trace_test_context = install_test_tracing("codex-core-tests");
|
||||
|
||||
let dispatch_span = submission_dispatch_span(&Submission {
|
||||
id: "sub-1".into(),
|
||||
@@ -2917,7 +2902,7 @@ async fn spawn_task_turn_span_inherits_dispatch_trace_context() {
|
||||
}
|
||||
}
|
||||
|
||||
init_test_tracing();
|
||||
let _trace_test_context = install_test_tracing("codex-core-tests");
|
||||
|
||||
let request_parent = W3cTraceContext {
|
||||
traceparent: Some("00-00000000000000000000000000000011-0000000000000022-01".into()),
|
||||
|
||||
Reference in New Issue
Block a user