Skip to content

Commit 76bcd19

Browse files
committed
fix(metrics): extend LLM latency histogram buckets
Signed-off-by: Yahoo <119646314+y4ho0@users.noreply.github.com>
1 parent 48b3b71 commit 76bcd19

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

crates/switchyard-server/src/metrics.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ const ROUTING_OVERHEAD_BUCKETS_MS: &[f64] = &[
1919
0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, 25.0, 50.0, 100.0, 250.0, 500.0, 1000.0, 2500.0, 5000.0,
2020
];
2121

22+
/// Bucket boundaries for model-call and end-to-end LLM latency histograms.
23+
/// Retains the SDK defaults through 10 seconds and extends them for long generations.
24+
const LLM_LATENCY_BUCKETS_MS: &[f64] = &[
25+
0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 7500.0,
26+
10_000.0, 15_000.0, 30_000.0, 60_000.0, 120_000.0, 300_000.0,
27+
];
28+
2229
struct Metrics {
2330
registry: Registry,
2431
provider: SdkMeterProvider,
@@ -43,6 +50,7 @@ fn initialize() -> Result<Metrics, String> {
4350
let mut builder = SdkMeterProvider::builder()
4451
.with_reader(exporter)
4552
.with_view(routing_overhead_buckets)
53+
.with_view(llm_latency_buckets)
4654
.with_resource(crate::observability::resource());
4755
if crate::observability::otlp_enabled("METRICS") {
4856
let exporter = opentelemetry_otlp::MetricExporter::builder()
@@ -84,6 +92,22 @@ fn routing_overhead_buckets(instrument: &Instrument) -> Option<Stream> {
8492
.ok()
8593
}
8694

95+
fn llm_latency_buckets(instrument: &Instrument) -> Option<Stream> {
96+
if !matches!(
97+
instrument.name(),
98+
"switchyard.model_call_latency_ms" | "switchyard.total_latency_ms"
99+
) {
100+
return None;
101+
}
102+
Stream::builder()
103+
.with_aggregation(Aggregation::ExplicitBucketHistogram {
104+
boundaries: LLM_LATENCY_BUCKETS_MS.to_vec(),
105+
record_min_max: true,
106+
})
107+
.build()
108+
.ok()
109+
}
110+
87111
/// Make the metrics exist before they get a hit. Nicer for dashboards but not really necessary.
88112
/// The HTTP status codes we seed are somewhat arbitrary.
89113
fn seed_outcome_metrics() {

crates/switchyard-server/tests/server.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,15 @@ async fn metrics_exposes_switchyard_otel_instruments() -> TestResult {
486486
)
487487
.is_some()
488488
);
489+
for metric in [
490+
"switchyard_model_call_latency_ms_bucket",
491+
"switchyard_total_latency_ms_bucket",
492+
] {
493+
assert!(
494+
metric_line(metrics, metric, &[("model", MODEL), ("le", "300000")]).is_some(),
495+
"missing five-minute bucket for {metric}"
496+
);
497+
}
489498
assert!(
490499
metric_line(
491500
metrics,

0 commit comments

Comments
 (0)