@@ -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+
2229struct 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.
89113fn seed_outcome_metrics ( ) {
0 commit comments