mirror of
https://github.com/openai/codex.git
synced 2026-10-24 18:18:41 +00:00
## Why Disabling OpenAI analytics also disabled explicitly configured OTLP metrics collectors. Users should be able to export metrics to their own collectors independently of `analytics.enabled`. ## What changed Apply the analytics preference only to the built-in `statsig` metrics exporter. Keep custom OTLP HTTP and gRPC exporters enabled regardless of that preference, and use `otel.metrics_exporter = "none"` to disable metrics export. Clarify these settings in config documentation and the schema. ## Testing Cover exporter selection across explicit and default analytics preferences. Update app-server and daemon telemetry tests to verify custom metrics export with analytics disabled, and worktree tests to disable metrics through the exporter setting. GitOrigin-RevId: 0c61f0f01e2b694db642ac7e7fd1dac9965c7d96
114 lines
4.1 KiB
Rust
114 lines
4.1 KiB
Rust
use crate::config::Config;
|
|
use codex_config::types::OtelExporterKind as Kind;
|
|
use codex_config::types::OtelHttpProtocol as Protocol;
|
|
use codex_features::Feature;
|
|
use codex_login::default_client::originator;
|
|
use codex_otel::OtelExporter;
|
|
use codex_otel::OtelHttpProtocol;
|
|
use codex_otel::OtelProvider;
|
|
use codex_otel::OtelSettings;
|
|
use codex_otel::OtelTlsConfig as OtelTlsSettings;
|
|
use std::error::Error;
|
|
|
|
/// Build an OpenTelemetry provider from the app Config.
|
|
///
|
|
/// Returns `None` when OTEL export is disabled.
|
|
pub fn build_provider(
|
|
config: &Config,
|
|
service_version: &str,
|
|
service_name_override: Option<&str>,
|
|
default_analytics_enabled: bool,
|
|
) -> Result<Option<OtelProvider>, Box<dyn Error>> {
|
|
let to_otel_exporter = |kind: &Kind| match kind {
|
|
Kind::None => OtelExporter::None,
|
|
Kind::Statsig => OtelExporter::Statsig,
|
|
Kind::OtlpHttp {
|
|
endpoint,
|
|
headers,
|
|
protocol,
|
|
tls,
|
|
} => {
|
|
let protocol = match protocol {
|
|
Protocol::Json => OtelHttpProtocol::Json,
|
|
Protocol::Binary => OtelHttpProtocol::Binary,
|
|
};
|
|
|
|
OtelExporter::OtlpHttp {
|
|
endpoint: endpoint.clone(),
|
|
headers: headers
|
|
.iter()
|
|
.map(|(k, v)| (k.clone(), v.clone()))
|
|
.collect(),
|
|
protocol,
|
|
tls: tls.as_ref().map(|config| OtelTlsSettings {
|
|
ca_certificate: config.ca_certificate.clone(),
|
|
client_certificate: config.client_certificate.clone(),
|
|
client_private_key: config.client_private_key.clone(),
|
|
}),
|
|
}
|
|
}
|
|
Kind::OtlpGrpc {
|
|
endpoint,
|
|
headers,
|
|
tls,
|
|
} => OtelExporter::OtlpGrpc {
|
|
endpoint: endpoint.clone(),
|
|
headers: headers
|
|
.iter()
|
|
.map(|(k, v)| (k.clone(), v.clone()))
|
|
.collect(),
|
|
tls: tls.as_ref().map(|config| OtelTlsSettings {
|
|
ca_certificate: config.ca_certificate.clone(),
|
|
client_certificate: config.client_certificate.clone(),
|
|
client_private_key: config.client_private_key.clone(),
|
|
}),
|
|
},
|
|
};
|
|
|
|
let exporter = to_otel_exporter(&config.otel.exporter);
|
|
let trace_exporter = to_otel_exporter(&config.otel.trace_exporter);
|
|
// Analytics consent controls the built-in exporter, not explicit OTLP collectors.
|
|
let metrics_exporter = if matches!(config.otel.metrics_exporter, Kind::Statsig)
|
|
&& !config
|
|
.analytics_enabled
|
|
.unwrap_or(default_analytics_enabled)
|
|
{
|
|
OtelExporter::None
|
|
} else {
|
|
to_otel_exporter(&config.otel.metrics_exporter)
|
|
};
|
|
|
|
let originator = originator();
|
|
let service_name = service_name_override.unwrap_or(originator.value.as_str());
|
|
let runtime_metrics = config.features.enabled(Feature::RuntimeMetrics);
|
|
|
|
OtelProvider::try_new(&OtelSettings {
|
|
http_client_factory: config.http_client_factory(),
|
|
service_name: service_name.to_string(),
|
|
service_version: service_version.to_string(),
|
|
codex_home: config.codex_home.to_path_buf(),
|
|
environment: config.otel.environment.to_string(),
|
|
exporter,
|
|
trace_exporter,
|
|
metrics_exporter,
|
|
runtime_metrics,
|
|
span_attributes: config.otel.span_attributes.clone(),
|
|
tracestate: config.otel.tracestate.clone(),
|
|
})
|
|
}
|
|
|
|
pub fn record_process_start(otel: Option<&OtelProvider>, originator: &str) {
|
|
let Some(metrics) = otel.and_then(OtelProvider::metrics) else {
|
|
return;
|
|
};
|
|
let _ = codex_otel::record_process_start_once(metrics, originator);
|
|
}
|
|
|
|
pub fn install_sqlite_telemetry(otel: Option<&OtelProvider>, originator: &str) {
|
|
let Some(metrics) = otel.and_then(OtelProvider::metrics) else {
|
|
return;
|
|
};
|
|
let telemetry = codex_rollout::sqlite_telemetry_recorder(metrics.clone(), originator);
|
|
let _ = codex_state::install_process_db_telemetry(telemetry);
|
|
}
|