mirror of
https://github.com/openai/codex.git
synced 2026-11-14 21:40:39 +00:00
## Why Managed OpenTelemetry requirements could not specify span attributes or tracestate metadata. ## What changed - Accept `otel.span_attributes` and `otel.tracestate` in requirements, merge them by attribute or member field, and expose them through app-server configuration and requirements reads. - Protect required entries and their ancestors from configuration writes while preserving unmanaged sibling values and their origins. For example, requiring `otel.tracestate.vendor.tenant` leaves `vendor.region` writable. Empty metadata maps impose no requirements. - Select Rustls when configuring an OTLP HTTP client certificate and private key so PEM client identities are accepted. ## Testing Add coverage for metadata precedence, effective configuration, field-level write protection, and preservation of unmanaged values. Add blocking and asynchronous HTTP client construction tests using generated PEM certificates and keys. GitOrigin-RevId: ada6000cc5e575b9a33451ec4aa58b6686dc20f7
121 lines
3.7 KiB
Rust
121 lines
3.7 KiB
Rust
use std::collections::BTreeMap;
|
|
use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
|
|
use codex_utils_absolute_path::AbsolutePathBuf;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
|
|
pub(crate) const STATSIG_OTLP_HTTP_ENDPOINT: &str = "https://ab.chatgpt.com/otlp/v1/metrics";
|
|
pub(crate) const STATSIG_API_KEY_HEADER: &str = "statsig-api-key";
|
|
pub(crate) const STATSIG_API_KEY: &str = "client-MkRuleRQBd6qakfnDYqJVR9JuXcY57Ljly3vi5JVUIO";
|
|
|
|
pub(crate) fn resolve_exporter(exporter: &OtelExporter) -> OtelExporter {
|
|
match exporter {
|
|
OtelExporter::Statsig => {
|
|
// Keep the built-in Statsig default off in debug builds so
|
|
// incremental local development and test runs do not emit
|
|
// best-effort OTEL traffic unless a test or binary opts into an
|
|
// explicit exporter configuration.
|
|
if cfg!(debug_assertions) {
|
|
return OtelExporter::None;
|
|
}
|
|
|
|
OtelExporter::OtlpHttp {
|
|
endpoint: STATSIG_OTLP_HTTP_ENDPOINT.to_string(),
|
|
headers: HashMap::from([(
|
|
STATSIG_API_KEY_HEADER.to_string(),
|
|
STATSIG_API_KEY.to_string(),
|
|
)]),
|
|
protocol: OtelHttpProtocol::Json,
|
|
tls: None,
|
|
}
|
|
}
|
|
_ => exporter.clone(),
|
|
}
|
|
}
|
|
|
|
/// Validates configured span attributes before they are attached to exported spans.
|
|
pub fn validate_span_attributes(attributes: &HashMap<String, String>) -> std::io::Result<()> {
|
|
if attributes.keys().any(String::is_empty) {
|
|
return Err(std::io::Error::new(
|
|
std::io::ErrorKind::InvalidInput,
|
|
"configured span attribute key must not be empty",
|
|
));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct OtelSettings {
|
|
pub http_client_factory: codex_http_client::HttpClientFactory,
|
|
pub environment: String,
|
|
pub service_name: String,
|
|
pub service_version: String,
|
|
pub codex_home: PathBuf,
|
|
pub exporter: OtelExporter,
|
|
pub trace_exporter: OtelExporter,
|
|
pub metrics_exporter: OtelExporter,
|
|
pub runtime_metrics: bool,
|
|
pub span_attributes: HashMap<String, String>,
|
|
pub tracestate: BTreeMap<String, BTreeMap<String, String>>,
|
|
}
|
|
|
|
/// Resolved Statsig metrics settings that another process can use to recreate
|
|
/// the built-in metrics exporter configuration without receiving generic
|
|
/// exporter credentials in-process.
|
|
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct StatsigMetricsSettings {
|
|
pub environment: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum OtelHttpProtocol {
|
|
/// HTTP protocol with binary protobuf
|
|
Binary,
|
|
/// HTTP protocol with JSON payload
|
|
Json,
|
|
}
|
|
|
|
#[derive(Clone, Debug, Default)]
|
|
pub struct OtelTlsConfig {
|
|
pub ca_certificate: Option<AbsolutePathBuf>,
|
|
pub client_certificate: Option<AbsolutePathBuf>,
|
|
pub client_private_key: Option<AbsolutePathBuf>,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub enum OtelExporter {
|
|
None,
|
|
/// Statsig metrics ingestion exporter using Codex-internal defaults.
|
|
///
|
|
/// This is intended for metrics only.
|
|
Statsig,
|
|
OtlpGrpc {
|
|
endpoint: String,
|
|
headers: HashMap<String, String>,
|
|
tls: Option<OtelTlsConfig>,
|
|
},
|
|
OtlpHttp {
|
|
endpoint: String,
|
|
headers: HashMap<String, String>,
|
|
protocol: OtelHttpProtocol,
|
|
tls: Option<OtelTlsConfig>,
|
|
},
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::OtelExporter;
|
|
use super::resolve_exporter;
|
|
|
|
#[test]
|
|
fn statsig_default_metrics_exporter_is_disabled_in_debug_builds() {
|
|
assert!(matches!(
|
|
resolve_exporter(&OtelExporter::Statsig),
|
|
OtelExporter::None
|
|
));
|
|
}
|
|
}
|