mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
Decouple thread initialization profiling
This commit is contained in:
@@ -530,7 +530,6 @@ async fn ingest_rejected_turn_steer(
|
||||
response: Box::new(sample_thread_resume_response(
|
||||
"thread-2", /*ephemeral*/ false, "gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
out,
|
||||
)
|
||||
@@ -604,7 +603,6 @@ async fn ingest_turn_prerequisites(
|
||||
response: Box::new(sample_thread_start_response(
|
||||
"thread-2", /*ephemeral*/ false, "gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
out,
|
||||
)
|
||||
@@ -628,7 +626,6 @@ async fn ingest_turn_prerequisites(
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(3),
|
||||
response: Box::new(sample_turn_start_response("turn-2")),
|
||||
thread_initialization: None,
|
||||
},
|
||||
out,
|
||||
)
|
||||
@@ -695,7 +692,6 @@ async fn ingest_review_prerequisites(
|
||||
response: Box::new(sample_thread_start_response(
|
||||
"thread-1", /*ephemeral*/ false, "gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
events,
|
||||
)
|
||||
@@ -1608,7 +1604,6 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize
|
||||
/*ephemeral*/ false,
|
||||
"gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -1653,7 +1648,6 @@ async fn initialize_caches_client_and_thread_lifecycle_publishes_once_initialize
|
||||
response: Box::new(sample_thread_resume_response(
|
||||
"thread-1", /*ephemeral*/ true, "gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -1724,7 +1718,6 @@ async fn unrelated_client_requests_are_ignored_by_reducer() {
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(3),
|
||||
response: Box::new(sample_turn_start_response("turn-2")),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -1750,7 +1743,6 @@ async fn unrelated_client_responses_are_ignored_by_reducer() {
|
||||
response: Box::new(ClientResponsePayload::ThreadArchive(
|
||||
ThreadArchiveResponse {},
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -1809,7 +1801,6 @@ async fn compaction_event_ingests_custom_fact() {
|
||||
Some(AppServerThreadSource::Subagent),
|
||||
Some(parent_thread_id.to_string()),
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -1917,7 +1908,6 @@ async fn guardian_review_event_ingests_custom_fact_with_optional_target_item() {
|
||||
/*ephemeral*/ false,
|
||||
"gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -2419,7 +2409,6 @@ async fn item_review_summaries_do_not_cross_threads_with_reused_item_ids() {
|
||||
response: Box::new(sample_thread_start_response(
|
||||
"thread-2", /*ephemeral*/ false, "gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -2707,7 +2696,6 @@ async fn subagent_thread_started_inherits_parent_connection_for_new_thread() {
|
||||
/*ephemeral*/ false,
|
||||
"gpt-5",
|
||||
)),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut events,
|
||||
)
|
||||
@@ -3462,7 +3450,6 @@ async fn accepted_turn_steer_emits_expected_event() {
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(4),
|
||||
response: Box::new(sample_turn_steer_response("turn-2")),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
@@ -3634,7 +3621,6 @@ async fn turn_start_error_response_discards_pending_start_request() {
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(3),
|
||||
response: Box::new(sample_turn_start_response("turn-2")),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
@@ -3934,7 +3920,6 @@ async fn accepted_steers_increment_turn_steer_count() {
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(4),
|
||||
response: Box::new(sample_turn_steer_response("turn-2")),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
@@ -3982,7 +3967,6 @@ async fn accepted_steers_increment_turn_steer_count() {
|
||||
connection_id: 7,
|
||||
request_id: RequestId::Integer(6),
|
||||
response: Box::new(sample_turn_steer_response("turn-2")),
|
||||
thread_initialization: None,
|
||||
},
|
||||
&mut out,
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::facts::PluginStateChangedInput;
|
||||
use crate::facts::SkillInvocation;
|
||||
use crate::facts::SkillInvokedInput;
|
||||
use crate::facts::SubAgentThreadStartedInput;
|
||||
use crate::facts::ThreadInitializationFact;
|
||||
use crate::facts::ThreadInitializationResponseFact;
|
||||
use crate::facts::TrackEventsContext;
|
||||
use crate::facts::TurnCodexErrorFact;
|
||||
use crate::facts::TurnProfileFact;
|
||||
@@ -318,7 +318,6 @@ impl AnalyticsEventsClient {
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
response: ClientResponsePayload,
|
||||
thread_initialization: Option<ThreadInitializationFact>,
|
||||
) {
|
||||
if !matches!(
|
||||
response,
|
||||
@@ -334,10 +333,13 @@ impl AnalyticsEventsClient {
|
||||
connection_id,
|
||||
request_id,
|
||||
response: Box::new(response),
|
||||
thread_initialization,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn track_thread_initialization_response(&self, fact: ThreadInitializationResponseFact) {
|
||||
self.record_fact(AnalyticsFact::ThreadInitializationResponse(Box::new(fact)));
|
||||
}
|
||||
|
||||
pub fn track_error_response(
|
||||
&self,
|
||||
connection_id: u64,
|
||||
|
||||
@@ -252,9 +252,7 @@ fn track_response_only_enqueues_analytics_relevant_responses() {
|
||||
(RequestId::Integer(4), sample_turn_start_response()),
|
||||
(RequestId::Integer(5), sample_turn_steer_response()),
|
||||
] {
|
||||
client.track_response(
|
||||
/*connection_id*/ 7, request_id, response, /*thread_initialization*/ None,
|
||||
);
|
||||
client.track_response(/*connection_id*/ 7, request_id, response);
|
||||
assert!(matches!(
|
||||
receiver.try_recv(),
|
||||
Ok(AnalyticsFact::ClientResponse { .. })
|
||||
@@ -265,7 +263,6 @@ fn track_response_only_enqueues_analytics_relevant_responses() {
|
||||
/*connection_id*/ 7,
|
||||
RequestId::Integer(6),
|
||||
ClientResponsePayload::ThreadArchive(ThreadArchiveResponse {}),
|
||||
/*thread_initialization*/ None,
|
||||
);
|
||||
assert!(matches!(receiver.try_recv(), Err(TryRecvError::Empty)));
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use codex_protocol::protocol::SkillScope;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use codex_protocol::request_permissions::RequestPermissionsResponse;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -98,7 +99,7 @@ pub enum ThreadInitializationMode {
|
||||
Resumed,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
pub struct ThreadInitializationProfile {
|
||||
pub duration_ms: u64,
|
||||
pub app_server_duration_ms: u64,
|
||||
@@ -117,11 +118,18 @@ pub struct ThreadInitializationProfile {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct ThreadInitializationFact {
|
||||
pub struct CompletedThreadInitialization {
|
||||
pub initialization_mode: ThreadInitializationMode,
|
||||
pub profile: ThreadInitializationProfile,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ThreadInitializationResponseFact {
|
||||
pub connection_id: u64,
|
||||
pub response: ClientResponsePayload,
|
||||
pub initialization: CompletedThreadInitialization,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TurnTokenUsageFact {
|
||||
pub turn_id: String,
|
||||
@@ -482,8 +490,8 @@ pub(crate) enum AnalyticsFact {
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
response: Box<ClientResponsePayload>,
|
||||
thread_initialization: Option<ThreadInitializationFact>,
|
||||
},
|
||||
ThreadInitializationResponse(Box<ThreadInitializationResponseFact>),
|
||||
ErrorResponse {
|
||||
connection_id: u64,
|
||||
request_id: RequestId,
|
||||
|
||||
@@ -31,14 +31,15 @@ pub use facts::CompactionReason;
|
||||
pub use facts::CompactionStatus;
|
||||
pub use facts::CompactionStrategy;
|
||||
pub use facts::CompactionTrigger;
|
||||
pub use facts::CompletedThreadInitialization;
|
||||
pub use facts::HookRunFact;
|
||||
pub use facts::InputError;
|
||||
pub use facts::InvocationType;
|
||||
pub use facts::SkillInvocation;
|
||||
pub use facts::SubAgentThreadStartedInput;
|
||||
pub use facts::ThreadInitializationFact;
|
||||
pub use facts::ThreadInitializationMode;
|
||||
pub use facts::ThreadInitializationProfile;
|
||||
pub use facts::ThreadInitializationResponseFact;
|
||||
pub use facts::TrackEventsContext;
|
||||
pub use facts::TurnCodexErrorFact;
|
||||
pub use facts::TurnProfile;
|
||||
|
||||
@@ -62,6 +62,7 @@ use crate::facts::AnalyticsJsonRpcError;
|
||||
use crate::facts::AppMentionedInput;
|
||||
use crate::facts::AppUsedInput;
|
||||
use crate::facts::CodexCompactionEvent;
|
||||
use crate::facts::CompletedThreadInitialization;
|
||||
use crate::facts::CustomAnalyticsFact;
|
||||
use crate::facts::HookRunInput;
|
||||
use crate::facts::PluginState;
|
||||
@@ -69,9 +70,9 @@ use crate::facts::PluginStateChangedInput;
|
||||
use crate::facts::PluginUsedInput;
|
||||
use crate::facts::SkillInvokedInput;
|
||||
use crate::facts::SubAgentThreadStartedInput;
|
||||
use crate::facts::ThreadInitializationFact;
|
||||
use crate::facts::ThreadInitializationMode;
|
||||
use crate::facts::ThreadInitializationProfile;
|
||||
use crate::facts::ThreadInitializationResponseFact;
|
||||
use crate::facts::TurnCodexError;
|
||||
use crate::facts::TurnCodexErrorFact;
|
||||
use crate::facts::TurnProfile;
|
||||
@@ -143,6 +144,30 @@ pub(crate) struct AnalyticsReducer {
|
||||
item_review_summaries: HashMap<ToolItemKey, ItemReviewSummary>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ThreadInitializationEventDetails {
|
||||
mode: ThreadInitializationMode,
|
||||
profile: Option<ThreadInitializationProfile>,
|
||||
}
|
||||
|
||||
impl ThreadInitializationEventDetails {
|
||||
fn without_profile(mode: ThreadInitializationMode) -> Self {
|
||||
Self {
|
||||
mode,
|
||||
profile: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CompletedThreadInitialization> for ThreadInitializationEventDetails {
|
||||
fn from(initialization: CompletedThreadInitialization) -> Self {
|
||||
Self {
|
||||
mode: initialization.initialization_mode,
|
||||
profile: Some(initialization.profile),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConnectionState {
|
||||
app_server_client: CodexAppServerClientMetadata,
|
||||
runtime: CodexRuntimeMetadata,
|
||||
@@ -408,13 +433,14 @@ impl AnalyticsReducer {
|
||||
connection_id,
|
||||
request_id,
|
||||
response,
|
||||
thread_initialization,
|
||||
} => {
|
||||
if let Some(response) = response.into_client_response(request_id) {
|
||||
self.ingest_response(connection_id, response, thread_initialization, out)
|
||||
.await;
|
||||
self.ingest_response(connection_id, response, out).await;
|
||||
}
|
||||
}
|
||||
AnalyticsFact::ThreadInitializationResponse(input) => {
|
||||
self.ingest_thread_initialization_response(*input, out);
|
||||
}
|
||||
AnalyticsFact::ErrorResponse {
|
||||
connection_id,
|
||||
request_id,
|
||||
@@ -764,7 +790,6 @@ impl AnalyticsReducer {
|
||||
&mut self,
|
||||
connection_id: u64,
|
||||
response: ClientResponse,
|
||||
thread_initialization: Option<ThreadInitializationFact>,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
match response {
|
||||
@@ -773,10 +798,9 @@ impl AnalyticsReducer {
|
||||
connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
thread_initialization
|
||||
.map(|initialization| initialization.initialization_mode)
|
||||
.unwrap_or(ThreadInitializationMode::New),
|
||||
thread_initialization.map(|initialization| initialization.profile),
|
||||
ThreadInitializationEventDetails::without_profile(
|
||||
ThreadInitializationMode::New,
|
||||
),
|
||||
out,
|
||||
);
|
||||
}
|
||||
@@ -785,8 +809,9 @@ impl AnalyticsReducer {
|
||||
connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::Resumed,
|
||||
thread_initialization.map(|initialization| initialization.profile),
|
||||
ThreadInitializationEventDetails::without_profile(
|
||||
ThreadInitializationMode::Resumed,
|
||||
),
|
||||
out,
|
||||
);
|
||||
}
|
||||
@@ -795,8 +820,9 @@ impl AnalyticsReducer {
|
||||
connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
ThreadInitializationMode::Forked,
|
||||
thread_initialization.map(|initialization| initialization.profile),
|
||||
ThreadInitializationEventDetails::without_profile(
|
||||
ThreadInitializationMode::Forked,
|
||||
),
|
||||
out,
|
||||
);
|
||||
}
|
||||
@@ -826,6 +852,38 @@ impl AnalyticsReducer {
|
||||
}
|
||||
}
|
||||
|
||||
fn ingest_thread_initialization_response(
|
||||
&mut self,
|
||||
input: ThreadInitializationResponseFact,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let initialization = input.initialization.into();
|
||||
match input.response {
|
||||
ClientResponsePayload::ThreadStart(response) => self.emit_thread_initialized(
|
||||
input.connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
initialization,
|
||||
out,
|
||||
),
|
||||
ClientResponsePayload::ThreadResume(response) => self.emit_thread_initialized(
|
||||
input.connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
initialization,
|
||||
out,
|
||||
),
|
||||
ClientResponsePayload::ThreadFork(response) => self.emit_thread_initialized(
|
||||
input.connection_id,
|
||||
response.thread,
|
||||
response.model,
|
||||
initialization,
|
||||
out,
|
||||
),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn ingest_server_request(&mut self, _connection_id: u64, request: ServerRequest) {
|
||||
match request {
|
||||
ServerRequest::CommandExecutionRequestApproval { request_id, params } => {
|
||||
@@ -1199,8 +1257,7 @@ impl AnalyticsReducer {
|
||||
connection_id: u64,
|
||||
thread: codex_app_server_protocol::Thread,
|
||||
model: String,
|
||||
initialization_mode: ThreadInitializationMode,
|
||||
profile: Option<ThreadInitializationProfile>,
|
||||
initialization: ThreadInitializationEventDetails,
|
||||
out: &mut Vec<TrackEventRequest>,
|
||||
) {
|
||||
let session_source: SessionSource = thread.source.into();
|
||||
@@ -1236,12 +1293,12 @@ impl AnalyticsReducer {
|
||||
model,
|
||||
ephemeral: thread.ephemeral,
|
||||
thread_source: thread_metadata.thread_source,
|
||||
initialization_mode,
|
||||
initialization_mode: initialization.mode,
|
||||
subagent_source: thread_metadata.subagent_source.clone(),
|
||||
parent_thread_id: thread_metadata.parent_thread_id,
|
||||
forked_from_thread_id,
|
||||
created_at: u64::try_from(thread.created_at).unwrap_or_default(),
|
||||
profile,
|
||||
profile: initialization.profile,
|
||||
},
|
||||
},
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user