From f71b306e3f554b9767f0807b5d48ae45587db482 Mon Sep 17 00:00:00 2001 From: Ahmed Ibrahim Date: Thu, 28 May 2026 11:05:52 -0700 Subject: [PATCH] Simplify startup telemetry event names --- .../analytics/src/analytics_client_tests.rs | 73 ++++++++----------- codex-rs/analytics/src/client.rs | 4 +- codex-rs/analytics/src/events.rs | 24 +++--- codex-rs/analytics/src/facts.rs | 2 +- codex-rs/analytics/src/reducer.rs | 28 +++---- codex-rs/app-server/src/lib.rs | 4 +- .../app-server/tests/suite/v2/thread_start.rs | 8 +- 7 files changed, 64 insertions(+), 79 deletions(-) diff --git a/codex-rs/analytics/src/analytics_client_tests.rs b/codex-rs/analytics/src/analytics_client_tests.rs index 75822e4b52..031cd756d5 100644 --- a/codex-rs/analytics/src/analytics_client_tests.rs +++ b/codex-rs/analytics/src/analytics_client_tests.rs @@ -1,11 +1,11 @@ use crate::client::AnalyticsEventsQueue; use crate::events::AppServerRpcTransport; +use crate::events::AppServerStartedEventParams; +use crate::events::AppServerStartedEventRequest; use crate::events::CodexAcceptedLineFingerprintsEventParams; use crate::events::CodexAcceptedLineFingerprintsEventRequest; use crate::events::CodexAppMentionedEventRequest; use crate::events::CodexAppServerClientMetadata; -use crate::events::CodexAppServerStartedEventParams; -use crate::events::CodexAppServerStartedEventRequest; use crate::events::CodexAppUsedEventRequest; use crate::events::CodexCommandExecutionEventParams; use crate::events::CodexCommandExecutionEventRequest; @@ -30,9 +30,9 @@ use crate::events::ReviewStatus; use crate::events::ReviewSubjectKind; use crate::events::ReviewTrigger; use crate::events::Reviewer; +use crate::events::ThreadInitializationTimingParams; use crate::events::ThreadInitializedEvent; use crate::events::ThreadInitializedEventParams; -use crate::events::ThreadStartTimingEventParams; use crate::events::ToolItemTerminalStatus; use crate::events::TrackEventRequest; use crate::events::codex_app_metadata; @@ -1334,11 +1334,11 @@ fn thread_initialized_event_serializes_expected_shape() { initialization_mode: ThreadInitializationMode::New, subagent_source: None, parent_thread_id: None, - thread_start_timing: ThreadStartTimingEventParams { - thread_start_duration_ms: Some(321), - thread_start_prepare_duration_ms: Some(111), - thread_start_spawn_duration_ms: Some(123), - thread_start_finalize_duration_ms: Some(87), + initialization_timing: ThreadInitializationTimingParams { + duration_ms: Some(321), + prepare_duration_ms: Some(111), + spawn_duration_ms: Some(123), + finalize_duration_ms: Some(87), }, created_at: 1, }, @@ -1372,10 +1372,10 @@ fn thread_initialized_event_serializes_expected_shape() { "initialization_mode": "new", "subagent_source": null, "parent_thread_id": null, - "thread_start_duration_ms": 321, - "thread_start_prepare_duration_ms": 111, - "thread_start_spawn_duration_ms": 123, - "thread_start_finalize_duration_ms": 87, + "duration_ms": 321, + "prepare_duration_ms": 111, + "spawn_duration_ms": 123, + "finalize_duration_ms": 87, "created_at": 1 } }) @@ -1384,12 +1384,12 @@ fn thread_initialized_event_serializes_expected_shape() { #[test] fn app_server_started_event_serializes_expected_shape() { - let event = TrackEventRequest::AppServerStarted(CodexAppServerStartedEventRequest { - event_type: "codex_app_server_started", - event_params: CodexAppServerStartedEventParams { + let event = TrackEventRequest::AppServerStarted(AppServerStartedEventRequest { + event_type: "app_server_started", + event_params: AppServerStartedEventParams { runtime: sample_runtime_metadata(), remote_control_enabled: true, - startup_duration_ms: 987, + duration_ms: 987, completed_at: 12, }, }); @@ -1399,7 +1399,7 @@ fn app_server_started_event_serializes_expected_shape() { assert_eq!( payload, json!({ - "event_type": "codex_app_server_started", + "event_type": "app_server_started", "event_params": { "runtime": { "codex_rs_version": "0.1.0", @@ -1408,7 +1408,7 @@ fn app_server_started_event_serializes_expected_shape() { "runtime_arch": "aarch64" }, "remote_control_enabled": true, - "startup_duration_ms": 987, + "duration_ms": 987, "completed_at": 12 } }) @@ -1691,20 +1691,14 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize payload[0]["event_params"]["runtime"]["runtime_arch"], "x86_64" ); + assert_eq!(payload[0]["event_params"]["duration_ms"], json!(null)); assert_eq!( - payload[0]["event_params"]["thread_start_duration_ms"], + payload[0]["event_params"]["prepare_duration_ms"], json!(null) ); + assert_eq!(payload[0]["event_params"]["spawn_duration_ms"], json!(null)); assert_eq!( - payload[0]["event_params"]["thread_start_prepare_duration_ms"], - json!(null) - ); - assert_eq!( - payload[0]["event_params"]["thread_start_spawn_duration_ms"], - json!(null) - ); - assert_eq!( - payload[0]["event_params"]["thread_start_finalize_duration_ms"], + payload[0]["event_params"]["finalize_duration_ms"], json!(null) ); } @@ -1720,7 +1714,7 @@ async fn app_server_started_fact_emits_event() { AppServerStartedInput { runtime: sample_runtime_metadata(), remote_control_enabled: true, - startup_duration_ms: 456, + duration_ms: 456, completed_at: 12, }, )), @@ -1732,7 +1726,7 @@ async fn app_server_started_fact_emits_event() { assert_eq!( payload, json!([{ - "event_type": "codex_app_server_started", + "event_type": "app_server_started", "event_params": { "runtime": { "codex_rs_version": "0.1.0", @@ -1741,7 +1735,7 @@ async fn app_server_started_fact_emits_event() { "runtime_arch": "aarch64" }, "remote_control_enabled": true, - "startup_duration_ms": 456, + "duration_ms": 456, "completed_at": 12 } }]) @@ -1783,20 +1777,11 @@ async fn thread_start_timing_fact_enriches_thread_initialized_event() { let payload = serde_json::to_value(&events).expect("serialize events"); assert_eq!(payload[0]["event_type"], json!("codex_thread_initialized")); + assert_eq!(payload[0]["event_params"]["duration_ms"], json!(222)); + assert_eq!(payload[0]["event_params"]["prepare_duration_ms"], json!(12)); + assert_eq!(payload[0]["event_params"]["spawn_duration_ms"], json!(123)); assert_eq!( - payload[0]["event_params"]["thread_start_duration_ms"], - json!(222) - ); - assert_eq!( - payload[0]["event_params"]["thread_start_prepare_duration_ms"], - json!(12) - ); - assert_eq!( - payload[0]["event_params"]["thread_start_spawn_duration_ms"], - json!(123) - ); - assert_eq!( - payload[0]["event_params"]["thread_start_finalize_duration_ms"], + payload[0]["event_params"]["finalize_duration_ms"], json!(87) ); } diff --git a/codex-rs/analytics/src/client.rs b/codex-rs/analytics/src/client.rs index 2ff425550b..75704494fe 100644 --- a/codex-rs/analytics/src/client.rs +++ b/codex-rs/analytics/src/client.rs @@ -166,12 +166,12 @@ impl AnalyticsEventsClient { }); } - pub fn track_app_server_started(&self, startup_duration_ms: u64, remote_control_enabled: bool) { + pub fn track_app_server_started(&self, duration_ms: u64, remote_control_enabled: bool) { self.record_fact(AnalyticsFact::Custom( CustomAnalyticsFact::AppServerStarted(AppServerStartedInput { runtime: current_runtime_metadata(), remote_control_enabled, - startup_duration_ms, + duration_ms, completed_at: now_unix_seconds(), }), )); diff --git a/codex-rs/analytics/src/events.rs b/codex-rs/analytics/src/events.rs index 4b74331115..0efbba2f18 100644 --- a/codex-rs/analytics/src/events.rs +++ b/codex-rs/analytics/src/events.rs @@ -56,7 +56,7 @@ pub(crate) struct TrackEventsRequest { #[serde(untagged)] pub(crate) enum TrackEventRequest { SkillInvocation(SkillInvocationEventRequest), - AppServerStarted(CodexAppServerStartedEventRequest), + AppServerStarted(AppServerStartedEventRequest), ThreadInitialized(ThreadInitializedEvent), GuardianReview(Box), AppMentioned(CodexAppMentionedEventRequest), @@ -146,25 +146,25 @@ pub(crate) struct CodexRuntimeMetadata { } #[derive(Serialize)] -pub(crate) struct CodexAppServerStartedEventParams { +pub(crate) struct AppServerStartedEventParams { pub(crate) runtime: CodexRuntimeMetadata, pub(crate) remote_control_enabled: bool, - pub(crate) startup_duration_ms: u64, + pub(crate) duration_ms: u64, pub(crate) completed_at: u64, } #[derive(Serialize)] -pub(crate) struct CodexAppServerStartedEventRequest { +pub(crate) struct AppServerStartedEventRequest { pub(crate) event_type: &'static str, - pub(crate) event_params: CodexAppServerStartedEventParams, + pub(crate) event_params: AppServerStartedEventParams, } #[derive(Default, Serialize)] -pub(crate) struct ThreadStartTimingEventParams { - pub(crate) thread_start_duration_ms: Option, - pub(crate) thread_start_prepare_duration_ms: Option, - pub(crate) thread_start_spawn_duration_ms: Option, - pub(crate) thread_start_finalize_duration_ms: Option, +pub(crate) struct ThreadInitializationTimingParams { + pub(crate) duration_ms: Option, + pub(crate) prepare_duration_ms: Option, + pub(crate) spawn_duration_ms: Option, + pub(crate) finalize_duration_ms: Option, } #[derive(Serialize)] @@ -180,7 +180,7 @@ pub(crate) struct ThreadInitializedEventParams { pub(crate) subagent_source: Option, pub(crate) parent_thread_id: Option, #[serde(flatten)] - pub(crate) thread_start_timing: ThreadStartTimingEventParams, + pub(crate) initialization_timing: ThreadInitializationTimingParams, pub(crate) created_at: u64, } @@ -1075,7 +1075,7 @@ pub(crate) fn subagent_thread_started_event_request( parent_thread_id: input .parent_thread_id .or_else(|| subagent_parent_thread_id(&input.subagent_source)), - thread_start_timing: ThreadStartTimingEventParams::default(), + initialization_timing: ThreadInitializationTimingParams::default(), created_at: input.created_at, }; ThreadInitializedEvent { diff --git a/codex-rs/analytics/src/facts.rs b/codex-rs/analytics/src/facts.rs index 4c043ac041..e57e58aa82 100644 --- a/codex-rs/analytics/src/facts.rs +++ b/codex-rs/analytics/src/facts.rs @@ -278,7 +278,7 @@ pub struct CodexCompactionEvent { pub(crate) struct AppServerStartedInput { pub runtime: CodexRuntimeMetadata, pub remote_control_enabled: bool, - pub startup_duration_ms: u64, + pub duration_ms: u64, pub completed_at: u64, } diff --git a/codex-rs/analytics/src/reducer.rs b/codex-rs/analytics/src/reducer.rs index 6b69fea18c..f5c0789c96 100644 --- a/codex-rs/analytics/src/reducer.rs +++ b/codex-rs/analytics/src/reducer.rs @@ -3,10 +3,10 @@ use crate::accepted_lines::accepted_line_fingerprint_event_requests; use crate::accepted_lines::accepted_line_fingerprints_from_unified_diff; use crate::accepted_lines::accepted_line_repo_hash_for_cwd; use crate::events::AppServerRpcTransport; +use crate::events::AppServerStartedEventParams; +use crate::events::AppServerStartedEventRequest; use crate::events::CodexAppMentionedEventRequest; use crate::events::CodexAppServerClientMetadata; -use crate::events::CodexAppServerStartedEventParams; -use crate::events::CodexAppServerStartedEventRequest; use crate::events::CodexAppUsedEventRequest; use crate::events::CodexCollabAgentToolCallEventParams; use crate::events::CodexCollabAgentToolCallEventRequest; @@ -45,9 +45,9 @@ use crate::events::ReviewTrigger; use crate::events::Reviewer; use crate::events::SkillInvocationEventParams; use crate::events::SkillInvocationEventRequest; +use crate::events::ThreadInitializationTimingParams; use crate::events::ThreadInitializedEvent; use crate::events::ThreadInitializedEventParams; -use crate::events::ThreadStartTimingEventParams; use crate::events::ToolItemFailureKind; use crate::events::ToolItemTerminalStatus; use crate::events::TrackEventRequest; @@ -537,12 +537,12 @@ impl AnalyticsReducer { out: &mut Vec, ) { out.push(TrackEventRequest::AppServerStarted( - CodexAppServerStartedEventRequest { - event_type: "codex_app_server_started", - event_params: CodexAppServerStartedEventParams { + AppServerStartedEventRequest { + event_type: "app_server_started", + event_params: AppServerStartedEventParams { runtime: input.runtime, remote_control_enabled: input.remote_control_enabled, - startup_duration_ms: input.startup_duration_ms, + duration_ms: input.duration_ms, completed_at: input.completed_at, }, }, @@ -1318,14 +1318,14 @@ impl AnalyticsReducer { initialization_mode, subagent_source: thread_metadata.subagent_source.clone(), parent_thread_id: thread_metadata.parent_thread_id, - thread_start_timing: match thread_start_timing { - Some(timing) => ThreadStartTimingEventParams { - thread_start_duration_ms: Some(timing.duration_ms), - thread_start_prepare_duration_ms: Some(timing.prepare_duration_ms), - thread_start_spawn_duration_ms: Some(timing.spawn_duration_ms), - thread_start_finalize_duration_ms: Some(timing.finalize_duration_ms), + initialization_timing: match thread_start_timing { + Some(timing) => ThreadInitializationTimingParams { + duration_ms: Some(timing.duration_ms), + prepare_duration_ms: Some(timing.prepare_duration_ms), + spawn_duration_ms: Some(timing.spawn_duration_ms), + finalize_duration_ms: Some(timing.finalize_duration_ms), }, - None => ThreadStartTimingEventParams::default(), + None => ThreadInitializationTimingParams::default(), }, created_at: u64::try_from(thread.created_at).unwrap_or_default(), }, diff --git a/codex-rs/app-server/src/lib.rs b/codex-rs/app-server/src/lib.rs index b711abb170..b416ecf434 100644 --- a/codex-rs/app-server/src/lib.rs +++ b/codex-rs/app-server/src/lib.rs @@ -1069,12 +1069,12 @@ pub async fn run_main_with_transport_options( info!("processor task exited (channel closed)"); } }); - let startup_duration_ms = app_server_started_at + let duration_ms = app_server_started_at .elapsed() .as_millis() .try_into() .unwrap_or(u64::MAX); - analytics_events_client.track_app_server_started(startup_duration_ms, remote_control_enabled); + analytics_events_client.track_app_server_started(duration_ms, remote_control_enabled); drop(transport_event_tx); diff --git a/codex-rs/app-server/tests/suite/v2/thread_start.rs b/codex-rs/app-server/tests/suite/v2/thread_start.rs index ddca8dc178..1bb4117557 100644 --- a/codex-rs/app-server/tests/suite/v2/thread_start.rs +++ b/codex-rs/app-server/tests/suite/v2/thread_start.rs @@ -448,10 +448,10 @@ async fn thread_start_tracks_thread_initialized_analytics() -> Result<()> { "user", ); let thread_start_timings = [ - "thread_start_duration_ms", - "thread_start_prepare_duration_ms", - "thread_start_spawn_duration_ms", - "thread_start_finalize_duration_ms", + "duration_ms", + "prepare_duration_ms", + "spawn_duration_ms", + "finalize_duration_ms", ] .map(|field| event["event_params"][field].as_u64().is_some()); assert_eq!(thread_start_timings, [true, true, true, true]);