mirror of
https://github.com/openai/codex.git
synced 2026-04-29 02:41:12 +03: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:
@@ -5,6 +5,7 @@ use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::RateLimitSnapshot;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use codex_protocol::protocol::W3cTraceContext;
|
||||
use futures::Stream;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -15,6 +16,9 @@ use std::task::Context;
|
||||
use std::task::Poll;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
pub const WS_REQUEST_HEADER_TRACEPARENT_CLIENT_METADATA_KEY: &str = "ws_request_header_traceparent";
|
||||
pub const WS_REQUEST_HEADER_TRACESTATE_CLIENT_METADATA_KEY: &str = "ws_request_header_tracestate";
|
||||
|
||||
/// Canonical input payload for the compaction endpoint.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct CompactionInput<'a> {
|
||||
@@ -215,6 +219,28 @@ pub struct ResponseCreateWsRequest {
|
||||
pub client_metadata: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
pub fn response_create_client_metadata(
|
||||
client_metadata: Option<HashMap<String, String>>,
|
||||
trace: Option<&W3cTraceContext>,
|
||||
) -> Option<HashMap<String, String>> {
|
||||
let mut client_metadata = client_metadata.unwrap_or_default();
|
||||
|
||||
if let Some(traceparent) = trace.and_then(|trace| trace.traceparent.as_deref()) {
|
||||
client_metadata.insert(
|
||||
WS_REQUEST_HEADER_TRACEPARENT_CLIENT_METADATA_KEY.to_string(),
|
||||
traceparent.to_string(),
|
||||
);
|
||||
}
|
||||
if let Some(tracestate) = trace.and_then(|trace| trace.tracestate.as_deref()) {
|
||||
client_metadata.insert(
|
||||
WS_REQUEST_HEADER_TRACESTATE_CLIENT_METADATA_KEY.to_string(),
|
||||
tracestate.to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
(!client_metadata.is_empty()).then_some(client_metadata)
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
|
||||
@@ -23,7 +23,10 @@ pub use crate::common::ResponseCreateWsRequest;
|
||||
pub use crate::common::ResponseEvent;
|
||||
pub use crate::common::ResponseStream;
|
||||
pub use crate::common::ResponsesApiRequest;
|
||||
pub use crate::common::WS_REQUEST_HEADER_TRACEPARENT_CLIENT_METADATA_KEY;
|
||||
pub use crate::common::WS_REQUEST_HEADER_TRACESTATE_CLIENT_METADATA_KEY;
|
||||
pub use crate::common::create_text_param_for_request;
|
||||
pub use crate::common::response_create_client_metadata;
|
||||
pub use crate::endpoint::compact::CompactClient;
|
||||
pub use crate::endpoint::memories::MemoriesClient;
|
||||
pub use crate::endpoint::models::ModelsClient;
|
||||
|
||||
Reference in New Issue
Block a user