Report code mode host request durations (#41452)

## Why

Code mode wall time should measure the host operation itself, without including
client-side response delays or idle time between requests.

## What changed

- Measure each execute, wait, and terminate request in the code mode host.
- Carry the duration through the stdio and gRPC protocols and use it for
  model-visible wall time.
- Emit a structured `codex.code_mode.host_timing` event correlated with the
  conversation, turn, tool call, and cell.

## Testing

- Cover successful and failed execution timing, delayed response reads,
  repeated waits, termination, and missing cells across stdio and gRPC.
- Verify timing survives protocol serialization and is reflected in app-server
  model output and structured telemetry.

GitOrigin-RevId: d24af30c3fc5820521b4beba1f9970714dad6482
This commit is contained in:
Adam Perry @ OpenAI
2026-08-29 02:52:58 +00:00
committed by copyberry
parent 75388bf321
commit 48e22a5fa0
34 changed files with 1398 additions and 259 deletions
@@ -60,25 +60,31 @@ pub(super) fn public_runtime_response(
RuntimeResponse::Yielded {
cell_id,
content_items,
code_mode_host_duration,
} => RuntimeResponse::Yielded {
cell_id: public_cell_id_from_protocol(generation, &cell_id),
content_items,
code_mode_host_duration,
},
RuntimeResponse::Terminated {
cell_id,
content_items,
code_mode_host_duration,
} => RuntimeResponse::Terminated {
cell_id: public_cell_id_from_protocol(generation, &cell_id),
content_items,
code_mode_host_duration,
},
RuntimeResponse::Result {
cell_id,
content_items,
error_text,
code_mode_host_duration,
} => RuntimeResponse::Result {
cell_id: public_cell_id_from_protocol(generation, &cell_id),
content_items,
error_text,
code_mode_host_duration,
},
}
}
@@ -773,6 +773,7 @@ async fn terminate_closes_cell_without_waiting_for_delegate_cleanup() {
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::LiveCell(WireRuntimeResponse::Terminated {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
}),
@@ -792,6 +793,7 @@ async fn terminate_closes_cell_without_waiting_for_delegate_cleanup() {
response_rx.await.expect("terminate reply"),
Ok(codex_code_mode_protocol::WaitOutcome::LiveCell(
codex_code_mode_protocol::RuntimeResponse::Terminated {
code_mode_host_duration: Some(Duration::ZERO),
cell_id: CellId::new("1".to_string()),
content_items: Vec::new(),
}
@@ -1096,6 +1098,7 @@ async fn mismatched_initial_response_fails_connection_and_closes_cell_once() {
id: RequestId::new(/*value*/ 2),
result: WireResult::Ok {
value: WireRuntimeResponse::Yielded {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("2".to_string()).into(),
content_items: Vec::new(),
},
@@ -1143,6 +1146,7 @@ async fn mismatched_wait_response_fails_connection() {
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::LiveCell(WireRuntimeResponse::Yielded {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("2".to_string()).into(),
content_items: Vec::new(),
}),
@@ -1187,6 +1191,7 @@ async fn mismatched_terminate_response_fails_connection() {
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::MissingCell(WireRuntimeResponse::Terminated {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("2".to_string()).into(),
content_items: Vec::new(),
}),
@@ -1239,6 +1244,7 @@ async fn remote_wait_accepts_durations_longer_than_five_minutes() {
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::LiveCell(WireRuntimeResponse::Yielded {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
}),
@@ -1252,6 +1258,7 @@ async fn remote_wait_accepts_durations_longer_than_five_minutes() {
response_rx.await.expect("wait reply"),
Ok(codex_code_mode_protocol::WaitOutcome::LiveCell(
codex_code_mode_protocol::RuntimeResponse::Yielded {
code_mode_host_duration: Some(Duration::ZERO),
cell_id: CellId::new("1".to_string()),
content_items: Vec::new(),
}
@@ -1416,6 +1423,7 @@ async fn cancelled_wait_is_retired_before_next_wait_is_sent() {
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::LiveCell(WireRuntimeResponse::Yielded {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
}),
@@ -1429,6 +1437,7 @@ async fn cancelled_wait_is_retired_before_next_wait_is_sent() {
second_rx.await.expect("second wait reply"),
Ok(codex_code_mode_protocol::WaitOutcome::LiveCell(
codex_code_mode_protocol::RuntimeResponse::Yielded {
code_mode_host_duration: Some(Duration::ZERO),
cell_id: CellId::new("1".to_string()),
content_items: Vec::new(),
}
@@ -1492,6 +1501,7 @@ async fn abandoned_execute_is_tracked_and_terminated_after_admission() {
id: RequestId::new(/*value*/ 2),
result: WireResult::Ok {
value: WireRuntimeResponse::Terminated {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
},
@@ -1506,6 +1516,7 @@ async fn abandoned_execute_is_tracked_and_terminated_after_admission() {
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::LiveCell(WireRuntimeResponse::Terminated {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
}),
@@ -1591,6 +1602,7 @@ async fn delivered_but_unclaimed_execute_is_terminated_when_the_caller_is_cancel
id: RequestId::new(/*value*/ 2),
result: WireResult::Ok {
value: WireRuntimeResponse::Terminated {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
},
@@ -1606,6 +1618,7 @@ async fn delivered_but_unclaimed_execute_is_terminated_when_the_caller_is_cancel
result: WireResult::Ok {
value: HostResponse::WaitCompleted {
outcome: WireWaitOutcome::LiveCell(WireRuntimeResponse::Terminated {
code_mode_host_duration_ns: 0,
cell_id: CellId::new("1".to_string()).into(),
content_items: Vec::new(),
}),
@@ -1652,6 +1665,7 @@ async fn session_accepts_more_than_4096_cells_without_growing_a_tombstone_set()
id: RequestId::new(request_id),
result: WireResult::Ok {
value: WireRuntimeResponse::Yielded {
code_mode_host_duration_ns: 0,
cell_id: CellId::new(cell_id.clone()).into(),
content_items: Vec::new(),
},