mirror of
https://github.com/openai/codex.git
synced 2026-05-05 22:01:37 +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:
@@ -59,7 +59,9 @@ use codex_api::common::ResponsesWsRequest;
|
||||
use codex_api::create_text_param_for_request;
|
||||
use codex_api::error::ApiError;
|
||||
use codex_api::requests::responses::Compression;
|
||||
use codex_api::response_create_client_metadata;
|
||||
use codex_otel::SessionTelemetry;
|
||||
use codex_otel::current_span_w3c_trace_context;
|
||||
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
@@ -69,6 +71,7 @@ use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::W3cTraceContext;
|
||||
use eventsource_stream::Event;
|
||||
use eventsource_stream::EventStreamError;
|
||||
use futures::StreamExt;
|
||||
@@ -1099,6 +1102,7 @@ impl ModelClientSession {
|
||||
service_tier: Option<ServiceTier>,
|
||||
turn_metadata_header: Option<&str>,
|
||||
warmup: bool,
|
||||
request_trace: Option<W3cTraceContext>,
|
||||
) -> Result<WebsocketStreamOutcome> {
|
||||
let auth_manager = self.client.state.auth_manager.clone();
|
||||
|
||||
@@ -1125,7 +1129,10 @@ impl ModelClientSession {
|
||||
service_tier,
|
||||
)?;
|
||||
let mut ws_payload = ResponseCreateWsRequest {
|
||||
client_metadata: build_ws_client_metadata(turn_metadata_header),
|
||||
client_metadata: response_create_client_metadata(
|
||||
build_ws_client_metadata(turn_metadata_header),
|
||||
request_trace.as_ref(),
|
||||
),
|
||||
..ResponseCreateWsRequest::from(&request)
|
||||
};
|
||||
if warmup {
|
||||
@@ -1249,6 +1256,7 @@ impl ModelClientSession {
|
||||
service_tier,
|
||||
turn_metadata_header,
|
||||
/*warmup*/ true,
|
||||
current_span_w3c_trace_context(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
@@ -1292,6 +1300,7 @@ impl ModelClientSession {
|
||||
match wire_api {
|
||||
WireApi::Responses => {
|
||||
if self.client.responses_websocket_enabled() {
|
||||
let request_trace = current_span_w3c_trace_context();
|
||||
match self
|
||||
.stream_responses_websocket(
|
||||
prompt,
|
||||
@@ -1302,6 +1311,7 @@ impl ModelClientSession {
|
||||
service_tier,
|
||||
turn_metadata_header,
|
||||
/*warmup*/ false,
|
||||
request_trace,
|
||||
)
|
||||
.await?
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user