Add trace_id to TurnStartedEvent (#23980)

## Why
[Recent PR](https://github.com/openai/codex/pull/22709) removed
`trace_id` from `TurnContextItem`.

## What changed
- Add to `TurnStartedEvent` so rollout consumers can correlate turns
with telemetry traces.
- Note that the branch name is out of date because I originally re-added
to `TurnContextItem`, but we decided to move it to `TurnStartedEvent`.

## Verification
- `cargo test -p codex-protocol`
- `cargo test -p codex-core --lib
regular_turn_emits_turn_started_without_waiting_for_startup_prewarm`
- `cargo test -p codex-core --test all
emits_warning_when_resumed_model_differs`
- `cargo test -p codex-rollout`
- `cargo test -p codex-state`
This commit is contained in:
mchen-oai
2026-05-22 13:10:56 -07:00
committed by GitHub
parent 36a71a88bf
commit 3c83e57bfa
16 changed files with 104 additions and 6 deletions
+1
View File
@@ -271,6 +271,7 @@ async fn get_status_returns_not_found_without_manager() {
async fn on_event_updates_status_from_task_started() {
let status = agent_status_from_event(&EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-1".to_string(),
trace_id: None,
started_at: None,
model_context_window: None,
collaboration_mode_kind: ModeKind::Default,
+1
View File
@@ -100,6 +100,7 @@ pub(crate) async fn run_compact_task(
) -> CodexResult<()> {
let start_event = EventMsg::TurnStarted(TurnStartedEvent {
turn_id: turn_context.sub_id.clone(),
trace_id: turn_context.trace_id.clone(),
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
model_context_window: turn_context.model_context_window(),
collaboration_mode_kind: turn_context.collaboration_mode.mode,
+1
View File
@@ -62,6 +62,7 @@ pub(crate) async fn run_remote_compact_task(
) -> CodexResult<()> {
let start_event = EventMsg::TurnStarted(TurnStartedEvent {
turn_id: turn_context.sub_id.clone(),
trace_id: turn_context.trace_id.clone(),
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
model_context_window: turn_context.model_context_window(),
collaboration_mode_kind: turn_context.collaboration_mode.mode,
+1
View File
@@ -78,6 +78,7 @@ pub(crate) async fn run_remote_compact_task(
) -> CodexResult<()> {
let start_event = EventMsg::TurnStarted(TurnStartedEvent {
turn_id: turn_context.sub_id.clone(),
trace_id: turn_context.trace_id.clone(),
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
model_context_window: turn_context.model_context_window(),
collaboration_mode_kind: turn_context.collaboration_mode.mode,
@@ -122,6 +122,7 @@ async fn record_initial_history_resumed_hydrates_previous_turn_settings_from_lif
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -189,6 +190,7 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: first_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -218,6 +220,7 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_com
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: rolled_back_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -289,6 +292,7 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_inc
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: first_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -318,6 +322,7 @@ async fn reconstruct_history_rollback_keeps_history_and_metadata_in_sync_for_inc
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: incomplete_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -381,6 +386,7 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: first_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -410,6 +416,7 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: second_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -438,6 +445,7 @@ async fn reconstruct_history_rollback_skips_non_user_turns_for_history_and_metad
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: standalone_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -501,6 +509,7 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: first_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -530,6 +539,7 @@ async fn reconstruct_history_rollback_counts_inter_agent_assistant_turns() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: assistant_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -590,6 +600,7 @@ async fn reconstruct_history_rollback_clears_history_and_metadata_when_exceeding
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: only_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -643,6 +654,7 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: user_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -671,6 +683,7 @@ async fn record_initial_history_resumed_rollback_skips_only_user_turns() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: standalone_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -716,6 +729,7 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: previous_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -743,6 +757,7 @@ async fn record_initial_history_resumed_rollback_drops_incomplete_user_turn_comp
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: incomplete_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -875,6 +890,7 @@ async fn reconstruct_history_legacy_compaction_without_replacement_history_clear
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: current_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -939,6 +955,7 @@ async fn record_initial_history_resumed_turn_context_after_compaction_reestablis
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: previous_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1043,6 +1060,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: previous_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1070,6 +1088,7 @@ async fn record_initial_history_resumed_aborted_turn_without_id_clears_active_tu
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: aborted_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1151,6 +1170,7 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: previous_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1178,6 +1198,7 @@ async fn record_initial_history_resumed_unmatched_abort_preserves_active_turn_fo
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: current_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1268,6 +1289,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: previous_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1295,6 +1317,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_compaction_clea
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: incomplete_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1346,6 +1369,7 @@ async fn record_initial_history_resumed_trailing_incomplete_turn_preserves_turn_
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: current_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1420,6 +1444,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: previous_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1447,6 +1472,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: compacted_incomplete_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -1470,6 +1496,7 @@ async fn record_initial_history_resumed_replaced_incomplete_compacted_turn_clear
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: replacing_turn_id,
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
+32 -6
View File
@@ -267,8 +267,24 @@ fn skill_message(text: &str) -> ResponseItem {
}
#[tokio::test]
async fn regular_turn_emits_turn_started_without_waiting_for_startup_prewarm() {
let (sess, tc, rx) = make_session_and_context_with_rx().await;
async fn regular_turn_emits_turn_started_with_trace_id_without_waiting_for_startup_prewarm() {
let _trace_test_context = install_test_tracing("codex-core-tests");
let request_parent = W3cTraceContext {
traceparent: Some("00-00000000000000000000000000000011-0000000000000022-01".into()),
tracestate: Some("vendor=value".into()),
};
let request_span = info_span!("app_server.request");
assert!(set_parent_from_w3c_trace_context(
&request_span,
&request_parent
));
let (sess, tc, rx) = make_session_and_context_with_rx()
.instrument(request_span)
.await;
assert_eq!(
tc.trace_id.as_deref(),
Some("00000000000000000000000000000011")
);
let (_tx, startup_prewarm_rx) = tokio::sync::oneshot::channel::<()>();
let handle = tokio::spawn(async move {
let _ = startup_prewarm_rx.await;
@@ -294,10 +310,11 @@ async fn regular_turn_emits_turn_started_without_waiting_for_startup_prewarm() {
.await
.expect("expected turn started event without waiting for startup prewarm")
.expect("channel open");
assert!(matches!(
first.msg,
EventMsg::TurnStarted(TurnStartedEvent { turn_id, .. }) if turn_id == tc.sub_id
));
let EventMsg::TurnStarted(turn_started) = first.msg else {
panic!("expected turn started event");
};
assert_eq!(turn_started.turn_id, tc.sub_id);
assert_eq!(turn_started.trace_id, tc.trace_id);
sess.abort_all_tasks(TurnAbortReason::Interrupted).await;
}
@@ -2378,6 +2395,7 @@ async fn record_initial_history_forked_hydrates_previous_turn_settings() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2573,6 +2591,7 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: first_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2600,6 +2619,7 @@ async fn thread_rollback_recomputes_previous_turn_settings_and_reference_context
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: rolled_back_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2684,6 +2704,7 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: first_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2709,6 +2730,7 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: compact_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2728,6 +2750,7 @@ async fn thread_rollback_restores_cleared_reference_context_item_after_compactio
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: rolled_back_turn_id.clone(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2783,6 +2806,7 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: "turn-1".to_string(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2808,6 +2832,7 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: "turn-2".to_string(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
@@ -2833,6 +2858,7 @@ async fn thread_rollback_persists_marker_and_replays_cumulatively() {
RolloutItem::EventMsg(EventMsg::TurnStarted(
codex_protocol::protocol::TurnStartedEvent {
turn_id: "turn-3".to_string(),
trace_id: None,
started_at: None,
model_context_window: Some(128_000),
collaboration_mode_kind: ModeKind::Default,
+1
View File
@@ -51,6 +51,7 @@ impl SessionTask for RegularTask {
// not wait on startup prewarm resolution.
let event = EventMsg::TurnStarted(TurnStartedEvent {
turn_id: ctx.sub_id.clone(),
trace_id: ctx.trace_id.clone(),
started_at: ctx.turn_timing_state.started_at_unix_secs().await,
model_context_window: ctx.model_context_window(),
collaboration_mode_kind: ctx.collaboration_mode.mode,
+1
View File
@@ -114,6 +114,7 @@ pub(crate) async fn execute_user_shell_command(
// freshly reinjected context before the summary/replacement history is applied.
let event = EventMsg::TurnStarted(TurnStartedEvent {
turn_id: turn_context.sub_id.clone(),
trace_id: turn_context.trace_id.clone(),
started_at: turn_context.turn_timing_state.started_at_unix_secs().await,
model_context_window: turn_context.model_context_window(),
collaboration_mode_kind: turn_context.collaboration_mode.mode,
@@ -187,6 +187,7 @@ fn out_of_range_truncation_drops_pre_user_active_turn_prefix() {
RolloutItem::ResponseItem(assistant_msg("a1")),
RolloutItem::EventMsg(EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-2".to_string(),
trace_id: None,
started_at: None,
model_context_window: None,
collaboration_mode_kind: Default::default(),
@@ -1307,6 +1308,7 @@ async fn interrupted_fork_snapshot_preserves_explicit_turn_id() {
InitialHistory::Forked(vec![
RolloutItem::EventMsg(EventMsg::TurnStarted(TurnStartedEvent {
turn_id: "turn-explicit".to_string(),
trace_id: None,
started_at: None,
model_context_window: None,
collaboration_mode_kind: Default::default(),