Make app-server OTEL startup best effort

This commit is contained in:
malsamiri
2026-06-29 09:17:11 -07:00
parent ccdfb4f342
commit cf51679e68
2 changed files with 83 additions and 8 deletions
+13 -8
View File
@@ -529,18 +529,23 @@ pub async fn run_main_with_transport_options(
}
};
let otel = codex_core::otel_init::build_provider(
let otel = match codex_core::otel_init::build_provider(
&config,
env!("CARGO_PKG_VERSION"),
Some(OTEL_SERVICE_NAME),
default_analytics_enabled,
)
.map_err(|e| {
std::io::Error::new(
ErrorKind::InvalidData,
format!("error loading otel config: {e}"),
)
})?;
) {
Ok(otel) => otel,
Err(err) => {
config_warnings.push(ConfigWarningNotification {
summary: "OpenTelemetry disabled; exporter initialization failed.".to_string(),
details: Some(err.to_string()),
path: None,
range: None,
});
None
}
};
codex_core::otel_init::record_process_start(otel.as_ref(), OTEL_SERVICE_NAME);
codex_core::otel_init::install_sqlite_telemetry(otel.as_ref(), OTEL_SERVICE_NAME);
let unix_socket_startup_lock = match &transport {
@@ -4,6 +4,7 @@ use app_test_support::create_final_assistant_message_sse_response;
use app_test_support::create_mock_responses_server_sequence_unchecked;
use app_test_support::to_response;
use codex_app_server_protocol::ClientInfo;
use codex_app_server_protocol::ConfigWarningNotification;
use codex_app_server_protocol::InitializeCapabilities;
use codex_app_server_protocol::InitializeResponse;
use codex_app_server_protocol::JSONRPCMessage;
@@ -62,6 +63,75 @@ async fn initialize_uses_client_info_name_as_originator() -> Result<()> {
Ok(())
}
#[tokio::test]
async fn initialize_continues_when_otel_metrics_exporter_config_is_invalid() -> Result<()> {
let responses = Vec::new();
let server = create_mock_responses_server_sequence_unchecked(responses).await;
let codex_home = TempDir::new()?;
create_config_toml_with_extra(
codex_home.path(),
&server.uri(),
"never",
r#"
[analytics]
enabled = true
[otel]
metrics_exporter = { otlp-grpc = { endpoint = "http://127.0.0.1:4317" } }
"#,
)?;
let mut mcp = TestAppServer::new_with_env(
codex_home.path(),
&[
("OTEL_METRICS_EXPORTER", Some("otlp")),
("OTEL_EXPORTER_OTLP_ENDPOINT", Some("http://127.0.0.1:4317")),
("OTEL_EXPORTER_OTLP_PROTOCOL", Some("grpc")),
("OTEL_EXPORTER_OTLP_COMPRESSION", Some("snappy")),
],
)
.await?;
let message = timeout(
DEFAULT_READ_TIMEOUT,
mcp.initialize_with_client_info(ClientInfo {
name: "codex_vscode".to_string(),
title: Some("Codex VS Code Extension".to_string()),
version: "0.1.0".to_string(),
}),
)
.await??;
let JSONRPCMessage::Response(_) = message else {
anyhow::bail!("expected initialize response, got {message:?}");
};
let notification = timeout(
DEFAULT_READ_TIMEOUT,
mcp.read_stream_until_notification_message("configWarning"),
)
.await??;
let warning: ConfigWarningNotification = serde_json::from_value(
notification
.params
.ok_or_else(|| anyhow::format_err!("config warning notification missing params"))?,
)?;
assert_eq!(
warning.summary,
"OpenTelemetry disabled; exporter initialization failed."
);
let details = warning
.details
.ok_or_else(|| anyhow::format_err!("config warning notification missing details"))?;
assert!(
details.contains("failed to build OTLP metrics exporter"),
"unexpected config warning details: {details}"
);
assert_eq!(warning.path, None);
assert_eq!(warning.range, None);
Ok(())
}
#[tokio::test]
async fn initialize_probe_does_not_override_originator() -> Result<()> {
let responses = Vec::new();