From 5c0e582c59892dbec89af78ae62c784d3da6c9cb Mon Sep 17 00:00:00 2001 From: Anton Panasenko Date: Sat, 18 Jul 2026 06:29:55 +0000 Subject: [PATCH] Add context to sampling retry logs (#33963) ## What changed - Add structured `turn_id`, `retries`, `max_retries`, and `sampling_error` fields to sampling-stream retry warnings. - Add a focused test that captures the warning and verifies its retry and error context. GitOrigin-RevId: dea868875d162b3f97b3c8a256359278f7267c1c --- codex-rs/core/src/responses_retry.rs | 8 ++++ codex-rs/core/src/responses_retry_tests.rs | 46 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 codex-rs/core/src/responses_retry_tests.rs diff --git a/codex-rs/core/src/responses_retry.rs b/codex-rs/core/src/responses_retry.rs index 9a55fc8114..2af97820f0 100644 --- a/codex-rs/core/src/responses_retry.rs +++ b/codex-rs/core/src/responses_retry.rs @@ -89,6 +89,10 @@ fn log_retry( match request { ResponsesStreamRequest::Sampling => { warn!( + turn_id = %turn_context.sub_id, + retries, + max_retries, + sampling_error = %err, "stream disconnected - retrying sampling request ({retries}/{max_retries} in {delay:?})...", ); } @@ -103,3 +107,7 @@ fn log_retry( } } } + +#[cfg(test)] +#[path = "responses_retry_tests.rs"] +mod tests; diff --git a/codex-rs/core/src/responses_retry_tests.rs b/codex-rs/core/src/responses_retry_tests.rs new file mode 100644 index 0000000000..94ad2e46d0 --- /dev/null +++ b/codex-rs/core/src/responses_retry_tests.rs @@ -0,0 +1,46 @@ +use super::ResponsesStreamRequest; +use super::log_retry; +use crate::session::tests::make_session_and_context; +use codex_protocol::error::CodexErr; +use std::time::Duration; +use tracing_test::internal::MockWriter; + +#[tokio::test] +async fn sampling_retry_logs_stream_error_context() { + let (_session, turn_context) = make_session_and_context().await; + let buffer: &'static std::sync::Mutex> = + Box::leak(Box::new(std::sync::Mutex::new(Vec::new()))); + let subscriber = tracing_subscriber::fmt() + .with_ansi(false) + .with_max_level(tracing::Level::WARN) + .with_writer(MockWriter::new(buffer)) + .finish(); + let _subscriber_guard = tracing::subscriber::set_default(subscriber); + + log_retry( + ResponsesStreamRequest::Sampling, + &turn_context, + &CodexErr::Stream( + "websocket closed by server before response.completed".to_string(), + None, + ), + /*retries*/ 2, + /*max_retries*/ 5, + Duration::from_secs(1), + ); + + let logs = String::from_utf8( + buffer + .lock() + .unwrap_or_else(std::sync::PoisonError::into_inner) + .clone(), + ) + .expect("retry log should be valid utf-8"); + assert!(logs.contains("stream disconnected - retrying sampling request")); + assert!(logs.contains(&format!("turn_id={}", turn_context.sub_id))); + assert!(logs.contains("retries=2")); + assert!(logs.contains("max_retries=5")); + assert!(logs.contains( + "sampling_error=stream disconnected before completion: websocket closed by server before response.completed" + )); +}