From 9a7e823e5be340e6e54bfac60edc6e1e0fd72d49 Mon Sep 17 00:00:00 2001 From: keith thornhill Date: Mon, 20 Jul 2026 16:21:11 +0000 Subject: [PATCH] Extend second-based latency histogram buckets (#34375) ## Why Requests longer than 10 seconds were grouped into the overflow bucket, limiting visibility into long-running request latency. ## What changed Add second-based duration histogram boundaries at 12, 15, 20, 30, 60, and 120 seconds. ## Testing Extend the duration histogram test to cover every new boundary and a 121-second overflow value. GitOrigin-RevId: 063a5d397dbd37d3b3940c7a1632b7b479e874a4 --- codex-rs/otel/src/metrics/client.rs | 3 ++- codex-rs/otel/tests/suite/timing.rs | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/codex-rs/otel/src/metrics/client.rs b/codex-rs/otel/src/metrics/client.rs index ec90584e0a..b0ba57a23f 100644 --- a/codex-rs/otel/src/metrics/client.rs +++ b/codex-rs/otel/src/metrics/client.rs @@ -53,7 +53,8 @@ const MILLISECOND_DURATION_BOUNDARIES: &[f64] = &[ ]; const SECOND_DURATION_UNIT: &str = "s"; const SECOND_DURATION_BOUNDARIES: &[f64] = &[ - 0.0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0, + 0.0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0, 12.0, + 15.0, 20.0, 30.0, 60.0, 120.0, ]; #[derive(Debug, Eq, Hash, PartialEq)] diff --git a/codex-rs/otel/tests/suite/timing.rs b/codex-rs/otel/tests/suite/timing.rs index 02259b6c72..2b119f4eb3 100644 --- a/codex-rs/otel/tests/suite/timing.rs +++ b/codex-rs/otel/tests/suite/timing.rs @@ -48,6 +48,7 @@ fn record_duration_keeps_whole_millisecond_behavior() -> Result<()> { Ok(()) } +/// Keeps long-running requests observable instead of collapsing their latency into the overflow bucket. #[test] fn record_duration_seconds_uses_fractional_seconds_and_scaled_buckets() -> Result<()> { let (metrics, exporter) = build_metrics_with_defaults(&[])?; @@ -56,6 +57,13 @@ fn record_duration_seconds_uses_fractional_seconds_and_scaled_buckets() -> Resul Duration::from_millis(200), Duration::from_secs(1), Duration::from_millis(4900), + Duration::from_secs(12), + Duration::from_secs(15), + Duration::from_secs(20), + Duration::from_secs(30), + Duration::from_secs(60), + Duration::from_secs(120), + Duration::from_secs(121), ] { metrics.record_duration_seconds_with_description( "codex.request_duration_seconds", @@ -73,14 +81,17 @@ fn record_duration_seconds_uses_fractional_seconds_and_scaled_buckets() -> Resul bounds, vec![ 0.0, 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0, + 12.0, 15.0, 20.0, 30.0, 60.0, 120.0, ] ); assert_eq!( bucket_counts, - vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0] + vec![ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 + ] ); - assert!((sum - 6.1).abs() < f64::EPSILON * 8.0); - assert_eq!(count, 3); + assert!((sum - 384.1).abs() < f64::EPSILON * 512.0); + assert_eq!(count, 10); let metric = crate::harness::find_metric(&resource_metrics, "codex.request_duration_seconds") .expect("codex.request_duration_seconds metric should exist"); assert_eq!(metric.unit(), "s");