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); let metrics_exporter = if config .analytics_enabled .unwrap_or(default_analytics_enabled) { to_otel_exporter(&config.otel.metrics_exporter) } else { OtelExporter::None }; let originator = originator(); let service_name = service_name_override.unwrap_or(originator.value.as_str()); let runtime_metrics = config.features.enabled(Feature::RuntimeMetrics); OtelProvider::from(&OtelSettings { 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(), })}/// Filter predicate for exporting only Codex-owned events via OTEL./// Keeps events that originated from codex_otel modulepub fn codex_export_filter(meta: &tracing::Metadata<'_>) -> bool { meta.target().starts_with("codex_otel")}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);}