[codex-analytics] remove ga flag (#19863)

This commit is contained in:
rhan-oai
2026-04-27 15:29:19 -04:00
committed by GitHub
Unverified
parent 85c1500569
commit 215d5a8f7c
17 changed files with 87 additions and 351 deletions
@@ -540,7 +540,6 @@ struct ListenerTaskContext {
outgoing: Arc<OutgoingMessageSender>,
pending_thread_unloads: Arc<Mutex<HashSet<ThreadId>>>,
analytics_events_client: AnalyticsEventsClient,
general_analytics_enabled: bool,
thread_watch_manager: ThreadWatchManager,
fallback_model_provider: String,
codex_home: PathBuf,
@@ -727,14 +726,12 @@ impl CodexMessageProcessor {
error: &JSONRPCErrorError,
error_type: Option<AnalyticsJsonRpcError>,
) {
if self.config.features.enabled(Feature::GeneralAnalytics) {
self.analytics_events_client.track_error_response(
request_id.connection_id.0,
request_id.request_id.clone(),
error.clone(),
error_type,
);
}
self.analytics_events_client.track_error_response(
request_id.connection_id.0,
request_id.request_id.clone(),
error.clone(),
error_type,
);
}
async fn load_thread(
@@ -2410,7 +2407,6 @@ impl CodexMessageProcessor {
outgoing: Arc::clone(&self.outgoing),
pending_thread_unloads: Arc::clone(&self.pending_thread_unloads),
analytics_events_client: self.analytics_events_client.clone(),
general_analytics_enabled: self.config.features.enabled(Feature::GeneralAnalytics),
thread_watch_manager: self.thread_watch_manager.clone(),
fallback_model_provider: self.config.model_provider_id.clone(),
codex_home: self.config.codex_home.to_path_buf(),
@@ -2749,17 +2745,15 @@ impl CodexMessageProcessor {
permission_profile,
reasoning_effort: config_snapshot.reasoning_effort,
};
if listener_task_context.general_analytics_enabled {
listener_task_context
.analytics_events_client
.track_response(
request_id.connection_id.0,
ClientResponse::ThreadStart {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
}
listener_task_context
.analytics_events_client
.track_response(
request_id.connection_id.0,
ClientResponse::ThreadStart {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
listener_task_context
.outgoing
@@ -4565,15 +4559,13 @@ impl CodexMessageProcessor {
permission_profile,
reasoning_effort: session_configured.reasoning_effort,
};
if self.config.features.enabled(Feature::GeneralAnalytics) {
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::ThreadResume {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
}
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::ThreadResume {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
let connection_id = request_id.connection_id;
let token_usage_thread = include_turns.then(|| response.thread.clone());
@@ -5296,15 +5288,13 @@ impl CodexMessageProcessor {
permission_profile,
reasoning_effort: session_configured.reasoning_effort,
};
if self.config.features.enabled(Feature::GeneralAnalytics) {
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::ThreadFork {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
}
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::ThreadFork {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
let connection_id = request_id.connection_id;
let token_usage_thread = include_turns.then(|| response.thread.clone());
@@ -7038,15 +7028,13 @@ impl CodexMessageProcessor {
};
let response = TurnStartResponse { turn };
if self.config.features.enabled(Feature::GeneralAnalytics) {
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::TurnStart {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
}
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::TurnStart {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
self.outgoing.send_response(request_id, response).await;
}
Err(err) => {
@@ -7172,15 +7160,13 @@ impl CodexMessageProcessor {
{
Ok(turn_id) => {
let response = TurnSteerResponse { turn_id };
if self.config.features.enabled(Feature::GeneralAnalytics) {
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::TurnSteer {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
}
self.analytics_events_client.track_response(
request_id.connection_id.0,
ClientResponse::TurnSteer {
request_id: request_id.request_id.clone(),
response: response.clone(),
},
);
self.outgoing.send_response(request_id, response).await;
}
Err(err) => {
@@ -7813,7 +7799,6 @@ impl CodexMessageProcessor {
outgoing: Arc::clone(&self.outgoing),
pending_thread_unloads: Arc::clone(&self.pending_thread_unloads),
analytics_events_client: self.analytics_events_client.clone(),
general_analytics_enabled: self.config.features.enabled(Feature::GeneralAnalytics),
thread_watch_manager: self.thread_watch_manager.clone(),
fallback_model_provider: self.config.model_provider_id.clone(),
codex_home: self.config.codex_home.to_path_buf(),
@@ -7931,7 +7916,6 @@ impl CodexMessageProcessor {
outgoing: Arc::clone(&self.outgoing),
pending_thread_unloads: Arc::clone(&self.pending_thread_unloads),
analytics_events_client: self.analytics_events_client.clone(),
general_analytics_enabled: self.config.features.enabled(Feature::GeneralAnalytics),
thread_watch_manager: self.thread_watch_manager.clone(),
fallback_model_provider: self.config.model_provider_id.clone(),
codex_home: self.config.codex_home.to_path_buf(),
@@ -7980,7 +7964,6 @@ impl CodexMessageProcessor {
thread_state_manager,
pending_thread_unloads,
analytics_events_client: _,
general_analytics_enabled: _,
thread_watch_manager,
fallback_model_provider,
codex_home,
@@ -8056,9 +8039,7 @@ impl CodexMessageProcessor {
conversation_id,
conversation.clone(),
thread_manager.clone(),
listener_task_context
.general_analytics_enabled
.then(|| listener_task_context.analytics_events_client.clone()),
Some(listener_task_context.analytics_events_client.clone()),
thread_outgoing,
thread_state.clone(),
thread_watch_manager.clone(),
+8 -11
View File
@@ -653,14 +653,12 @@ impl MessageProcessor {
}
}
}
if self.config.features.enabled(Feature::GeneralAnalytics) {
self.analytics_events_client.track_initialize(
connection_id.0,
analytics_initialize_params,
originator,
self.rpc_transport,
);
}
self.analytics_events_client.track_initialize(
connection_id.0,
analytics_initialize_params,
originator,
self.rpc_transport,
);
set_default_client_residency_requirement(self.config.enforce_residency.value());
if let Ok(mut suffix) = USER_AGENT_SUFFIX.lock() {
*suffix = Some(user_agent_suffix);
@@ -716,9 +714,8 @@ impl MessageProcessor {
return Err(invalid_request(experimental_required_message(reason)));
}
let connection_id = connection_request_id.connection_id;
if self.config.features.enabled(Feature::GeneralAnalytics)
&& let ClientRequest::TurnStart { request_id, .. }
| ClientRequest::TurnSteer { request_id, .. } = &codex_request
if let ClientRequest::TurnStart { request_id, .. }
| ClientRequest::TurnSteer { request_id, .. } = &codex_request
{
self.analytics_events_client.track_request(
connection_id.0,
@@ -79,24 +79,6 @@ async fn app_server_default_analytics_enabled_with_flag() -> Result<()> {
Ok(())
}
pub(crate) async fn enable_analytics_capture(server: &MockServer, codex_home: &Path) -> Result<()> {
let config_path = codex_home.join("config.toml");
let config_toml = std::fs::read_to_string(&config_path)?;
if !config_toml.contains("[features]") {
std::fs::write(
&config_path,
format!("{config_toml}\n[features]\ngeneral_analytics = true\n"),
)?;
} else if !config_toml.contains("general_analytics") {
std::fs::write(
&config_path,
config_toml.replace("[features]\n", "[features]\ngeneral_analytics = true\n"),
)?;
}
mount_analytics_capture(server, codex_home).await
}
pub(crate) async fn mount_analytics_capture(server: &MockServer, codex_home: &Path) -> Result<()> {
Mock::given(method("POST"))
.and(path("/codex/analytics-events/events"))
@@ -42,7 +42,7 @@ use wiremock::matchers::method;
use wiremock::matchers::path;
use super::analytics::assert_basic_thread_initialized_event;
use super::analytics::enable_analytics_capture;
use super::analytics::mount_analytics_capture;
use super::analytics::thread_initialized_event;
use super::analytics::wait_for_analytics_payload;
@@ -385,13 +385,8 @@ async fn thread_fork_tracks_thread_initialized_analytics() -> Result<()> {
let server = create_mock_responses_server_repeating_assistant("Done").await;
let codex_home = TempDir::new()?;
create_config_toml_with_chatgpt_base_url(
codex_home.path(),
&server.uri(),
&server.uri(),
/*general_analytics_enabled*/ true,
)?;
enable_analytics_capture(&server, codex_home.path()).await?;
create_config_toml_with_chatgpt_base_url(codex_home.path(), &server.uri(), &server.uri())?;
mount_analytics_capture(&server, codex_home.path()).await?;
let conversation_id = create_fake_rollout(
codex_home.path(),
@@ -496,7 +491,6 @@ async fn thread_fork_surfaces_cloud_requirements_load_errors() -> Result<()> {
codex_home.path(),
&model_server.uri(),
&chatgpt_base_url,
/*general_analytics_enabled*/ false,
)?;
write_chatgpt_auth(
codex_home.path(),
@@ -793,13 +787,7 @@ fn create_config_toml_with_chatgpt_base_url(
codex_home: &Path,
server_uri: &str,
chatgpt_base_url: &str,
general_analytics_enabled: bool,
) -> std::io::Result<()> {
let general_analytics_toml = if general_analytics_enabled {
"\ngeneral_analytics = true".to_string()
} else {
"\ngeneral_analytics = false".to_string()
};
let config_toml = codex_home.join("config.toml");
std::fs::write(
config_toml,
@@ -812,9 +800,6 @@ chatgpt_base_url = "{chatgpt_base_url}"
model_provider = "mock_provider"
[features]
{general_analytics_toml}
[model_providers.mock_provider]
name = "Mock provider for test"
base_url = "{server_uri}/v1"
@@ -84,7 +84,7 @@ use wiremock::matchers::method;
use wiremock::matchers::path;
use super::analytics::assert_basic_thread_initialized_event;
use super::analytics::enable_analytics_capture;
use super::analytics::mount_analytics_capture;
use super::analytics::thread_initialized_event;
use super::analytics::wait_for_analytics_payload;
@@ -185,10 +185,7 @@ async fn thread_goal_get_rejects_unmaterialized_thread() -> Result<()> {
let config = std::fs::read_to_string(&config_path)?;
std::fs::write(
&config_path,
config.replace(
"general_analytics = true\n",
"general_analytics = true\ngoals = true\n",
),
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
)?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
@@ -238,13 +235,8 @@ async fn thread_resume_tracks_thread_initialized_analytics() -> Result<()> {
let server = create_mock_responses_server_repeating_assistant("Done").await;
let codex_home = TempDir::new()?;
create_config_toml_with_chatgpt_base_url(
codex_home.path(),
&server.uri(),
&server.uri(),
/*general_analytics_enabled*/ true,
)?;
enable_analytics_capture(&server, codex_home.path()).await?;
create_config_toml_with_chatgpt_base_url(codex_home.path(), &server.uri(), &server.uri())?;
mount_analytics_capture(&server, codex_home.path()).await?;
let conversation_id = create_fake_rollout_with_text_elements(
codex_home.path(),
@@ -400,10 +392,7 @@ async fn thread_resume_emits_active_goal_update_before_continuation() -> Result<
let config = std::fs::read_to_string(&config_path)?;
std::fs::write(
&config_path,
config.replace(
"general_analytics = true\n",
"general_analytics = true\ngoals = true\n",
),
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
)?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
@@ -507,10 +496,7 @@ async fn thread_goal_set_preserves_budget_limited_same_objective() -> Result<()>
let config = std::fs::read_to_string(&config_path)?;
std::fs::write(
&config_path,
config.replace(
"general_analytics = true\n",
"general_analytics = true\ngoals = true\n",
),
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
)?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
@@ -608,10 +594,7 @@ async fn thread_goal_clear_deletes_goal_and_notifies() -> Result<()> {
let config = std::fs::read_to_string(&config_path)?;
std::fs::write(
&config_path,
config.replace(
"general_analytics = true\n",
"general_analytics = true\ngoals = true\n",
),
config.replace("personality = true\n", "personality = true\ngoals = true\n"),
)?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
@@ -2414,7 +2397,6 @@ async fn thread_resume_surfaces_cloud_requirements_load_errors() -> Result<()> {
codex_home.path(),
&model_server.uri(),
&chatgpt_base_url,
/*general_analytics_enabled*/ false,
)?;
write_chatgpt_auth(
codex_home.path(),
@@ -2859,7 +2841,6 @@ model_provider = "mock_provider"
[features]
personality = true
general_analytics = true
[model_providers.mock_provider]
name = "Mock provider for test"
@@ -2890,7 +2871,6 @@ model_provider = "mock_provider"
[features]
personality = true
general_analytics = true
[model_providers.mock_provider]
name = "Mock provider for test"
@@ -2907,13 +2887,7 @@ fn create_config_toml_with_chatgpt_base_url(
codex_home: &std::path::Path,
server_uri: &str,
chatgpt_base_url: &str,
general_analytics_enabled: bool,
) -> std::io::Result<()> {
let general_analytics_toml = if general_analytics_enabled {
"\ngeneral_analytics = true".to_string()
} else {
"\ngeneral_analytics = false".to_string()
};
let config_toml = codex_home.join("config.toml");
std::fs::write(
config_toml,
@@ -2928,7 +2902,6 @@ model_provider = "mock_provider"
[features]
personality = true
{general_analytics_toml}
[model_providers.mock_provider]
name = "Mock provider for test"
@@ -34,7 +34,6 @@ use serde_json::Value;
use serde_json::json;
use std::path::Path;
use std::path::PathBuf;
use std::time::Duration;
use tempfile::TempDir;
use tokio::time::timeout;
use wiremock::Mock;
@@ -265,12 +264,7 @@ async fn thread_start_tracks_thread_initialized_analytics() -> Result<()> {
let server = create_mock_responses_server_repeating_assistant("Done").await;
let codex_home = TempDir::new()?;
create_config_toml_with_chatgpt_base_url(
codex_home.path(),
&server.uri(),
&server.uri(),
/*general_analytics_enabled*/ true,
)?;
create_config_toml_with_chatgpt_base_url(codex_home.path(), &server.uri(), &server.uri())?;
mount_analytics_capture(&server, codex_home.path()).await?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
@@ -293,54 +287,6 @@ async fn thread_start_tracks_thread_initialized_analytics() -> Result<()> {
Ok(())
}
#[tokio::test]
async fn thread_start_does_not_track_thread_initialized_analytics_without_feature() -> Result<()> {
let server = create_mock_responses_server_repeating_assistant("Done").await;
let codex_home = TempDir::new()?;
create_config_toml_with_chatgpt_base_url(
codex_home.path(),
&server.uri(),
&server.uri(),
/*general_analytics_enabled*/ false,
)?;
mount_analytics_capture(&server, codex_home.path()).await?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
let req_id = mcp
.send_thread_start_request(ThreadStartParams::default())
.await?;
let resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(req_id)),
)
.await??;
let _ = to_response::<ThreadStartResponse>(resp)?;
assert_no_thread_initialized_analytics(&server, Duration::from_millis(250)).await?;
Ok(())
}
async fn assert_no_thread_initialized_analytics(
server: &MockServer,
wait_duration: Duration,
) -> Result<()> {
tokio::time::sleep(wait_duration).await;
let requests = server.received_requests().await.unwrap_or_default();
for request in requests.iter().filter(|request| {
request.method == "POST" && request.url.path() == "/codex/analytics-events/events"
}) {
let payload: Value = serde_json::from_slice(&request.body)?;
assert!(
thread_initialized_event(&payload).is_err(),
"thread analytics should be gated off when general_analytics is disabled; payload={payload}"
);
}
Ok(())
}
#[tokio::test]
async fn thread_start_respects_project_config_from_cwd() -> Result<()> {
let server = create_mock_responses_server_repeating_assistant("Done").await;
@@ -643,7 +589,6 @@ async fn thread_start_surfaces_cloud_requirements_load_errors() -> Result<()> {
codex_home.path(),
&model_server.uri(),
&chatgpt_base_url,
/*general_analytics_enabled*/ false,
)?;
write_chatgpt_auth(
codex_home.path(),
@@ -966,13 +911,7 @@ fn create_config_toml_with_chatgpt_base_url(
codex_home: &Path,
server_uri: &str,
chatgpt_base_url: &str,
general_analytics_enabled: bool,
) -> std::io::Result<()> {
let general_analytics_toml = if general_analytics_enabled {
"\ngeneral_analytics = true".to_string()
} else {
"\ngeneral_analytics = false".to_string()
};
let config_toml = codex_home.join("config.toml");
std::fs::write(
config_toml,
@@ -985,9 +924,6 @@ chatgpt_base_url = "{chatgpt_base_url}"
model_provider = "mock_provider"
[features]
{general_analytics_toml}
[model_providers.mock_provider]
name = "Mock provider for test"
base_url = "{server_uri}/v1"
@@ -78,7 +78,6 @@ use std::path::Path;
use tempfile::TempDir;
use tokio::time::timeout;
use super::analytics::enable_analytics_capture;
use super::analytics::mount_analytics_capture;
use super::analytics::wait_for_analytics_event;
@@ -463,7 +462,7 @@ async fn turn_start_tracks_turn_event_analytics() -> Result<()> {
&server.uri(),
&server.uri(),
)?;
enable_analytics_capture(&server, codex_home.path()).await?;
mount_analytics_capture(&server, codex_home.path()).await?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -538,77 +537,6 @@ async fn turn_start_tracks_turn_event_analytics() -> Result<()> {
Ok(())
}
#[tokio::test]
async fn turn_start_does_not_track_turn_event_analytics_without_feature() -> Result<()> {
let responses = vec![create_final_assistant_message_sse_response("Done")?];
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
write_mock_responses_config_toml_with_chatgpt_base_url(
codex_home.path(),
&server.uri(),
&server.uri(),
)?;
let config_path = codex_home.path().join("config.toml");
let config_toml = std::fs::read_to_string(&config_path)?;
std::fs::write(
&config_path,
format!("{config_toml}\n[features]\ngeneral_analytics = false\n"),
)?;
mount_analytics_capture(&server, codex_home.path()).await?;
let mut mcp = McpProcess::new_without_managed_config(codex_home.path()).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
let thread_req = mcp
.send_thread_start_request(ThreadStartParams {
model: Some("mock-model".to_string()),
..Default::default()
})
.await?;
let thread_resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(thread_req)),
)
.await??;
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(thread_resp)?;
let turn_req = mcp
.send_turn_start_request(TurnStartParams {
thread_id: thread.id,
input: vec![V2UserInput::Text {
text: "hello".to_string(),
text_elements: Vec::new(),
}],
..Default::default()
})
.await?;
let turn_resp: JSONRPCResponse = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_response_message(RequestId::Integer(turn_req)),
)
.await??;
let _ = to_response::<TurnStartResponse>(turn_resp)?;
timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_notification_message("turn/completed"),
)
.await??;
let turn_event = wait_for_analytics_event(
&server,
std::time::Duration::from_millis(250),
"codex_turn_event",
)
.await;
assert!(
turn_event.is_err(),
"turn analytics should be gated off when general_analytics is disabled"
);
Ok(())
}
#[tokio::test]
async fn turn_start_accepts_text_at_limit_with_mention_item() -> Result<()> {
let responses = vec![create_final_assistant_message_sse_response("Done")?];
@@ -24,7 +24,7 @@ use codex_protocol::user_input::MAX_USER_INPUT_TEXT_CHARS;
use tempfile::TempDir;
use tokio::time::timeout;
use super::analytics::enable_analytics_capture;
use super::analytics::mount_analytics_capture;
use super::analytics::wait_for_analytics_event;
const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
@@ -41,7 +41,7 @@ async fn turn_steer_requires_active_turn() -> Result<()> {
&server.uri(),
&server.uri(),
)?;
enable_analytics_capture(&server, &codex_home).await?;
mount_analytics_capture(&server, &codex_home).await?;
let mut mcp = McpProcess::new_without_managed_config(&codex_home).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -125,7 +125,7 @@ async fn turn_steer_rejects_oversized_text_input() -> Result<()> {
&server.uri(),
&server.uri(),
)?;
enable_analytics_capture(&server, &codex_home).await?;
mount_analytics_capture(&server, &codex_home).await?;
let mut mcp = McpProcess::new_without_managed_config(&codex_home).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
@@ -234,7 +234,7 @@ async fn turn_steer_returns_active_turn_id() -> Result<()> {
&server.uri(),
&server.uri(),
)?;
enable_analytics_capture(&server, &codex_home).await?;
mount_analytics_capture(&server, &codex_home).await?;
let mut mcp = McpProcess::new_without_managed_config(&codex_home).await?;
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
-6
View File
@@ -421,9 +421,6 @@
"fast_mode": {
"type": "boolean"
},
"general_analytics": {
"type": "boolean"
},
"goals": {
"type": "boolean"
},
@@ -2631,9 +2628,6 @@
"fast_mode": {
"type": "boolean"
},
"general_analytics": {
"type": "boolean"
},
"goals": {
"type": "boolean"
},
-1
View File
@@ -262,7 +262,6 @@ impl AgentControl {
parent_thread_id, ..
},
)) = notification_source.as_ref()
&& new_thread.thread.enabled(Feature::GeneralAnalytics)
{
let client_metadata = match state.get_thread(*parent_thread_id).await {
Ok(parent_thread) => {
+10 -12
View File
@@ -104,18 +104,16 @@ pub(crate) async fn run_codex_thread_interactive(
}))
.or_cancel(&cancel_token)
.await??;
if parent_session.enabled(codex_features::Feature::GeneralAnalytics) {
let thread_config = codex.thread_config_snapshot().await;
let client_metadata = parent_session.app_server_client_metadata().await;
emit_subagent_session_started(
&parent_session.services.analytics_events_client,
client_metadata,
codex.session.conversation_id,
Some(parent_session.conversation_id),
thread_config,
subagent_source,
);
}
let thread_config = codex.thread_config_snapshot().await;
let client_metadata = parent_session.app_server_client_metadata().await;
emit_subagent_session_started(
&parent_session.services.analytics_events_client,
client_metadata,
codex.session.conversation_id,
Some(parent_session.conversation_id),
thread_config,
subagent_source,
);
let codex = Arc::new(codex);
// Use a child token so parent cancel cascades but we can scope it to this task
-7
View File
@@ -18,7 +18,6 @@ use codex_analytics::CompactionStatus;
use codex_analytics::CompactionStrategy;
use codex_analytics::CompactionTrigger;
use codex_analytics::now_unix_seconds;
use codex_features::Feature;
use codex_protocol::error::CodexErr;
use codex_protocol::error::Result as CodexResult;
use codex_protocol::items::ContextCompactionItem;
@@ -295,7 +294,6 @@ async fn run_compact_task_inner_impl(
}
pub(crate) struct CompactionAnalyticsAttempt {
enabled: bool,
thread_id: String,
turn_id: String,
trigger: CompactionTrigger,
@@ -316,10 +314,8 @@ impl CompactionAnalyticsAttempt {
implementation: CompactionImplementation,
phase: CompactionPhase,
) -> Self {
let enabled = sess.enabled(Feature::GeneralAnalytics);
let active_context_tokens_before = sess.get_total_token_usage().await;
Self {
enabled,
thread_id: sess.conversation_id.to_string(),
turn_id: turn_context.sub_id.clone(),
trigger,
@@ -338,9 +334,6 @@ impl CompactionAnalyticsAttempt {
status: CompactionStatus,
error: Option<String>,
) {
if !self.enabled {
return;
}
let active_context_tokens_after = sess.get_total_token_usage().await;
sess.services
.analytics_events_client
-10
View File
@@ -6,7 +6,6 @@ use codex_analytics::GuardianReviewDecision;
use codex_analytics::GuardianReviewFailureReason;
use codex_analytics::GuardianReviewTerminalStatus;
use codex_analytics::GuardianReviewTrackContext;
use codex_features::Feature;
use codex_protocol::config_types::ApprovalsReviewer;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::EventMsg;
@@ -161,13 +160,9 @@ pub(crate) fn is_guardian_reviewer_source(
fn track_guardian_review(
session: &Session,
turn: &TurnContext,
tracking: &GuardianReviewTrackContext,
result: GuardianReviewAnalyticsResult,
) {
if !turn.config.features.enabled(Feature::GeneralAnalytics) {
return;
}
session
.services
.analytics_events_client
@@ -279,7 +274,6 @@ async fn run_guardian_review(
{
track_guardian_review(
session.as_ref(),
turn.as_ref(),
&review_tracking,
GuardianReviewAnalyticsResult {
decision: GuardianReviewDecision::Aborted,
@@ -325,7 +319,6 @@ async fn run_guardian_review(
let approved = matches!(assessment.outcome, GuardianAssessmentOutcome::Allow);
track_guardian_review(
session.as_ref(),
turn.as_ref(),
&review_tracking,
GuardianReviewAnalyticsResult {
decision: if approved {
@@ -356,7 +349,6 @@ async fn run_guardian_review(
.to_string();
track_guardian_review(
session.as_ref(),
turn.as_ref(),
&review_tracking,
GuardianReviewAnalyticsResult {
decision: GuardianReviewDecision::Denied,
@@ -395,7 +387,6 @@ async fn run_guardian_review(
GuardianReviewError::Cancelled => {
track_guardian_review(
session.as_ref(),
turn.as_ref(),
&review_tracking,
GuardianReviewAnalyticsResult {
decision: GuardianReviewDecision::Aborted,
@@ -437,7 +428,6 @@ async fn run_guardian_review(
let rationale = format!("Automatic approval review failed: {message}");
track_guardian_review(
session.as_ref(),
turn.as_ref(),
&review_tracking,
GuardianReviewAnalyticsResult {
decision: GuardianReviewDecision::Denied,
+9 -11
View File
@@ -163,17 +163,15 @@ pub(super) async fn run(session: &Arc<Session>, config: Arc<Config>) {
.get_agent_config_snapshot(thread_id)
.await
{
if session.enabled(Feature::GeneralAnalytics) {
let client_metadata = session.app_server_client_metadata().await;
emit_subagent_session_started(
&session.services.analytics_events_client,
client_metadata,
thread_id,
/*parent_thread_id*/ None,
thread_config,
SubAgentSource::MemoryConsolidation,
);
}
let client_metadata = session.app_server_client_metadata().await;
emit_subagent_session_started(
&session.services.analytics_events_client,
client_metadata,
thread_id,
/*parent_thread_id*/ None,
thread_config,
SubAgentSource::MemoryConsolidation,
);
} else {
warn!("failed to load memory consolidation thread config for analytics: {thread_id}");
}
-4
View File
@@ -662,10 +662,6 @@ async fn track_turn_resolved_config_analytics(
turn_context: &TurnContext,
input: &[UserInput],
) {
if !sess.enabled(Feature::GeneralAnalytics) {
return;
}
let thread_config = {
let state = sess.state.lock().await;
state.session_configuration.thread_config_snapshot()
-8
View File
@@ -128,8 +128,6 @@ pub enum Feature {
CodexGitCommit,
/// Enable runtime metrics snapshots via a manual reader.
RuntimeMetrics,
/// Enable thread lifecycle analytics emitted via the app-server analytics pipeline.
GeneralAnalytics,
/// Persist rollout metadata to a local SQLite database.
Sqlite,
/// Enable startup memory extraction and file-backed memory consolidation.
@@ -712,12 +710,6 @@ pub const FEATURES: &[FeatureSpec] = &[
stage: Stage::UnderDevelopment,
default_enabled: false,
},
FeatureSpec {
id: Feature::GeneralAnalytics,
key: "general_analytics",
stage: Stage::Stable,
default_enabled: true,
},
FeatureSpec {
id: Feature::Sqlite,
key: "sqlite",
-6
View File
@@ -156,12 +156,6 @@ fn browser_controls_are_stable_and_enabled_by_default() {
assert_eq!(feature_for_key("computer_use"), Some(Feature::ComputerUse));
}
#[test]
fn general_analytics_is_stable_and_enabled_by_default() {
assert_eq!(Feature::GeneralAnalytics.stage(), Stage::Stable);
assert_eq!(Feature::GeneralAnalytics.default_enabled(), true);
}
#[test]
fn use_linux_sandbox_bwrap_is_a_removed_feature_key() {
assert_eq!(