mirror of
https://github.com/openai/codex.git
synced 2026-10-30 19:18:49 +00:00
## Why OTEL exporter headers can contain credentials. Configuration responses exposed these values in effective config, source layers, managed requirements, and write-override metadata. ## What changed Replace header values with `[redacted]` across these responses for log, trace, and metrics exporters while preserving header names. Keep the original values available to runtime exporters, and redact them in debug output. Update protocol schemas and generated client documentation to describe the redacted values. ## Testing Add coverage for effective config and source-layer redaction, managed requirements, and single and batch write-override metadata, including header names containing dots. Extend telemetry integration coverage to verify that runtime requests still carry the configured header value. GitOrigin-RevId: ad24e8b91e615bd36c03c4c0ca205ac64bbd8cbf
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(|(name, value)| (name.clone(), value.as_str().to_owned()))
|
|
.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(|(name, value)| (name.clone(), value.as_str().to_owned()))
|
|
.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);
|
|
}
|