fix metrics_exporter inconsistencies

This commit is contained in:
michael mcgrew
2026-02-11 15:01:40 -05:00
parent f8092de827
commit f801b231cc
3 changed files with 131 additions and 12 deletions

View File

@@ -106,6 +106,18 @@ through that shared tracing pipeline.
OTEL resolution follows the same defaults as Codex core (`environment = "dev"`,
`exporter = "none"`, `trace_exporter = exporter`, `metrics_exporter = "statsig"`), and
`log_user_prompt` is accepted for compatibility but ignored by the proxy.
Standalone mode also honors top-level `[analytics].enabled`; when it is `false`, metrics export is
disabled (`metrics_exporter = "none"`), even if a metrics exporter is configured under `[otel]`.
Example:
```toml
[analytics]
enabled = false
[otel]
metrics_exporter = "statsig" # ignored while analytics is disabled
```
To filter proxy logs locally, use:

View File

@@ -30,6 +30,12 @@ struct StandaloneConfig {
config_missing: bool,
network: NetworkProxyConfig,
otel: standalone_otel::StandaloneOtelConfigToml,
analytics_enabled: bool,
}
#[derive(Debug, Deserialize, Default)]
struct StandaloneAnalyticsConfigToml {
enabled: Option<bool>,
}
#[derive(Debug, Deserialize, Default)]
@@ -38,6 +44,8 @@ struct StandaloneConfigToml {
network: NetworkProxyConfig,
#[serde(default)]
otel: standalone_otel::StandaloneOtelConfigToml,
#[serde(default)]
analytics: Option<StandaloneAnalyticsConfigToml>,
}
#[tokio::main]
@@ -50,10 +58,16 @@ async fn main() -> Result<()> {
config_missing,
network,
otel: otel_config,
analytics_enabled,
} = config;
let otel_provider = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
standalone_otel::build_provider(otel_config, codex_home, env!("CARGO_PKG_VERSION"))
standalone_otel::build_provider(
otel_config,
analytics_enabled,
codex_home,
env!("CARGO_PKG_VERSION"),
)
})) {
Ok(Ok(otel)) => otel,
Ok(Err(err)) => {
@@ -122,16 +136,22 @@ async fn load_standalone_config() -> Result<StandaloneConfig> {
}
};
let (network, otel, config_missing) = match raw {
let (network, otel, analytics_enabled, config_missing) = match raw {
Some(raw) => {
let parsed: StandaloneConfigToml = toml::from_str(&raw)
.with_context(|| format!("failed to parse {}", config_path.display()))?;
(parsed.network, parsed.otel, false)
let StandaloneConfigToml {
network,
otel,
analytics,
} = parsed;
(network, otel, resolve_analytics_enabled(analytics), false)
}
None => (
NetworkProxyConfig::default(),
standalone_otel::StandaloneOtelConfigToml::default(),
true,
true,
),
};
@@ -141,9 +161,14 @@ async fn load_standalone_config() -> Result<StandaloneConfig> {
config_missing,
network,
otel,
analytics_enabled,
})
}
fn resolve_analytics_enabled(analytics: Option<StandaloneAnalyticsConfigToml>) -> bool {
analytics.and_then(|a| a.enabled).unwrap_or(true)
}
struct StandaloneConfigReloader;
#[async_trait]
@@ -162,3 +187,35 @@ impl ConfigReloader for StandaloneConfigReloader {
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn standalone_config_analytics_defaults_enabled_when_omitted() {
let parsed: StandaloneConfigToml = toml::from_str(
r#"
[network]
enabled = true
"#,
)
.unwrap();
assert_eq!(resolve_analytics_enabled(parsed.analytics), true);
}
#[test]
fn standalone_config_analytics_respects_disabled_flag() {
let parsed: StandaloneConfigToml = toml::from_str(
r#"
[analytics]
enabled = false
"#,
)
.unwrap();
assert_eq!(resolve_analytics_enabled(parsed.analytics), false);
}
}

View File

@@ -82,12 +82,17 @@ pub(crate) fn parse_otel_config(raw: &str) -> Result<StandaloneOtelConfigToml, t
pub(crate) fn resolve_otel_config(
config: StandaloneOtelConfigToml,
analytics_enabled: bool,
) -> ResolvedStandaloneOtelConfig {
let exporter = config.exporter.unwrap_or(StandaloneOtelExporterKind::None);
let trace_exporter = config.trace_exporter.unwrap_or_else(|| exporter.clone());
let metrics_exporter = config
.metrics_exporter
.unwrap_or(StandaloneOtelExporterKind::Statsig);
let metrics_exporter = if analytics_enabled {
config
.metrics_exporter
.unwrap_or(StandaloneOtelExporterKind::Statsig)
} else {
StandaloneOtelExporterKind::None
};
ResolvedStandaloneOtelConfig {
environment: config
@@ -101,10 +106,11 @@ pub(crate) fn resolve_otel_config(
pub(crate) fn build_provider(
config: StandaloneOtelConfigToml,
analytics_enabled: bool,
codex_home: PathBuf,
service_version: &str,
) -> Result<Option<OtelProvider>, Box<dyn Error>> {
let resolved = resolve_otel_config(config);
let resolved = resolve_otel_config(config, analytics_enabled);
let settings = OtelSettings {
environment: resolved.environment,
service_name: STANDALONE_SERVICE_NAME.to_string(),
@@ -175,7 +181,7 @@ enabled = true
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed);
let resolved = resolve_otel_config(parsed, true);
assert_eq!(
resolved,
@@ -198,7 +204,7 @@ exporter = { otlp-http = { endpoint = "https://collector.example/v1/logs", proto
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed);
let resolved = resolve_otel_config(parsed, true);
assert_eq!(
resolved,
@@ -230,7 +236,7 @@ trace_exporter = { otlp-grpc = { endpoint = "https://collector.example:4317" } }
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed);
let resolved = resolve_otel_config(parsed, true);
assert_eq!(
resolved,
@@ -256,7 +262,7 @@ log_user_prompt = true
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed);
let resolved = resolve_otel_config(parsed, true);
assert_eq!(
resolved,
@@ -278,7 +284,7 @@ future_field = "ignored"
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed);
let resolved = resolve_otel_config(parsed, true);
assert_eq!(
resolved,
@@ -290,4 +296,48 @@ future_field = "ignored"
}
);
}
#[test]
fn parse_metrics_exporter_defaults_to_none_when_analytics_disabled() {
let parsed = parse_otel_config(
r#"
[otel]
environment = "staging"
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed, false);
assert_eq!(
resolved,
ResolvedStandaloneOtelConfig {
environment: "staging".to_string(),
exporter: StandaloneOtelExporterKind::None,
trace_exporter: StandaloneOtelExporterKind::None,
metrics_exporter: StandaloneOtelExporterKind::None,
}
);
}
#[test]
fn parse_metrics_exporter_is_none_when_analytics_disabled_even_if_explicitly_set() {
let parsed = parse_otel_config(
r#"
[otel]
metrics_exporter = { otlp-grpc = { endpoint = "https://collector.example:4317" } }
"#,
)
.unwrap();
let resolved = resolve_otel_config(parsed, false);
assert_eq!(
resolved,
ResolvedStandaloneOtelConfig {
environment: "dev".to_string(),
exporter: StandaloneOtelExporterKind::None,
trace_exporter: StandaloneOtelExporterKind::None,
metrics_exporter: StandaloneOtelExporterKind::None,
}
);
}
}