@@ -312,6 +312,27 @@ var (
312312 append ([]string {"fairness_id" , "priority" , "outcome" , "inference_pool" }, modelLabels ... ),
313313 )
314314
315+ flowControlSLORequestQueueDuration = prometheus .NewHistogramVec (
316+ prometheus.HistogramOpts {
317+ Subsystem : inferenceExtension ,
318+ Name : "flow_control_slo_request_queue_duration_seconds" ,
319+ Help : metricsutil .HelpMsgWithStability ("Distribution of the total time requests spend in the EPP flow control layer, partitioned by SLO class." , compbasemetrics .ALPHA ),
320+ Buckets : []float64 {
321+ 0.0001 , 0.0005 , 0.001 , 0.005 , 0.01 , 0.025 , 0.05 , 0.1 , 0.25 , 0.5 , 1.0 , 2.5 , 5.0 , 10.0 , 30.0 , 60.0 ,
322+ },
323+ },
324+ []string {"slo_class" , "outcome" , "inference_pool" },
325+ )
326+
327+ flowControlSLOIncomingRequestsTotal = prometheus .NewCounterVec (
328+ prometheus.CounterOpts {
329+ Subsystem : inferenceExtension ,
330+ Name : "flow_control_slo_incoming_requests_total" ,
331+ Help : metricsutil .HelpMsgWithStability ("Total number of requests that entered the EPP flow control layer via EnqueueAndWait." , compbasemetrics .ALPHA ),
332+ },
333+ []string {"slo_class" , "inference_pool" },
334+ )
335+
315336 // Deprecated: Use llm_d_router_epp_flow_control_dispatch_cycle_duration_seconds instead.
316337 // Tracked in: https://github.com/llm-d/llm-d-inference-scheduler/issues/1070
317338 flowControlDispatchCycleDuration = prometheus .NewHistogramVec (
@@ -348,7 +369,7 @@ var (
348369 Name : "flow_control_queue_size" ,
349370 Help : metricsutil .HelpMsgWithStability ("[Deprecated: Use llm_d_router_epp_flow_control_queue_size] Current number of requests actively held in the Flow Control queue." , compbasemetrics .ALPHA ),
350371 },
351- append ([]string {"fairness_id" , "priority" , "inference_pool" }, modelLabels ... ),
372+ append ([]string {"fairness_id" , "priority" , "inference_pool" , "slo_class" }, modelLabels ... ),
352373 )
353374
354375 // Deprecated: Use llm_d_router_epp_flow_control_queue_bytes instead.
@@ -359,7 +380,7 @@ var (
359380 Name : "flow_control_queue_bytes" ,
360381 Help : metricsutil .HelpMsgWithStability ("[Deprecated: Use llm_d_router_epp_flow_control_queue_bytes] Current total size in bytes of requests actively held in the Flow Control queue." , compbasemetrics .ALPHA ),
361382 },
362- append ([]string {"fairness_id" , "priority" , "inference_pool" }, modelLabels ... ),
383+ append ([]string {"fairness_id" , "priority" , "inference_pool" , "slo_class" }, modelLabels ... ),
363384 )
364385
365386 // Deprecated: Use llm_d_router_epp_flow_control_pool_saturation instead.
@@ -459,6 +480,8 @@ func Register(customCollectors ...prometheus.Collector) {
459480 metrics .Registry .MustRegister (llmdInferenceExtensionInfo )
460481 metrics .Registry .MustRegister (flowControlRequestQueueDuration )
461482 metrics .Registry .MustRegister (llmdFlowControlRequestQueueDuration )
483+ metrics .Registry .MustRegister (flowControlSLORequestQueueDuration )
484+ metrics .Registry .MustRegister (flowControlSLOIncomingRequestsTotal )
462485 metrics .Registry .MustRegister (flowControlDispatchCycleDuration )
463486 metrics .Registry .MustRegister (llmdFlowControlDispatchCycleDuration )
464487 metrics .Registry .MustRegister (flowControlQueueSize )
@@ -525,6 +548,8 @@ func Reset() {
525548 llmdInferenceExtensionInfo .Reset ()
526549 flowControlRequestQueueDuration .Reset ()
527550 llmdFlowControlRequestQueueDuration .Reset ()
551+ flowControlSLORequestQueueDuration .Reset ()
552+ flowControlSLOIncomingRequestsTotal .Reset ()
528553 flowControlQueueSize .Reset ()
529554 llmdFlowControlQueueSize .Reset ()
530555 flowControlQueueBytes .Reset ()
@@ -779,6 +804,59 @@ func RecordFlowControlRequestQueueDuration(
779804 ).Observe (duration .Seconds ())
780805}
781806
807+ // SLO class constants label for flow control SLO metrics (bounded buckets for the TTFT SLO header in ms).
808+ const (
809+ SLOClassNone = "none"
810+ SLOClassBelowMS200 = "below_ms_200"
811+ SLOClassMS200to399 = "ms_200_399"
812+ SLOClassMS400to599 = "ms_400_599"
813+ SLOClassMS600to799 = "ms_600_799"
814+ SLOClassMS800to1000 = "ms_800_1000"
815+ SLOClassAboveMS1000 = "above_ms_1000"
816+ )
817+
818+ // ClassifySLO maps a raw SLO header value (in milliseconds) to a bounded SLO class label.
819+ // Returns SLOClassNone when the header is absent or unparseable.
820+ func ClassifySLO (rawHeaderValue string ) string {
821+ if rawHeaderValue == "" {
822+ return SLOClassNone
823+ }
824+ ms , err := strconv .ParseInt (rawHeaderValue , 10 , 64 )
825+ if err != nil || ms < 0 {
826+ return SLOClassNone
827+ }
828+ switch {
829+ case ms < 200 :
830+ return SLOClassBelowMS200
831+ case ms < 400 :
832+ return SLOClassMS200to399
833+ case ms < 600 :
834+ return SLOClassMS400to599
835+ case ms < 800 :
836+ return SLOClassMS600to799
837+ case ms <= 1000 :
838+ return SLOClassMS800to1000
839+ default :
840+ return SLOClassAboveMS1000
841+ }
842+ }
843+
844+ // RecordFlowControlSLORequestQueueDuration records the queue duration for a request partitioned by its
845+ // SLO class (derived from the TTFT SLO header "x-slo-ttft-ms").
846+ func RecordFlowControlSLORequestQueueDuration (
847+ sloClass , outcome , inferencePool string ,
848+ duration time.Duration ,
849+ ) {
850+ flowControlSLORequestQueueDuration .WithLabelValues (
851+ sloClass , outcome , inferencePool ,
852+ ).Observe (duration .Seconds ())
853+ }
854+
855+ // RecordFlowControlSLOIncomingRequest increments the count of requests that entered flow control at EnqueueAndWait.
856+ func RecordFlowControlSLOIncomingRequest (sloClass , inferencePool string ) {
857+ flowControlSLOIncomingRequestsTotal .WithLabelValues (sloClass , inferencePool ).Inc ()
858+ }
859+
782860// RecordFlowControlDispatchCycleDuration records the duration of a dispatch cycle in the Flow Control layer.
783861func RecordFlowControlDispatchCycleDuration (duration time.Duration ) {
784862 flowControlDispatchCycleDuration .WithLabelValues ().Observe (duration .Seconds ())
@@ -800,26 +878,26 @@ func RecordFlowControlRequestEnqueueDuration(
800878}
801879
802880// IncFlowControlQueueSize increments the Flow Control queue size gauge.
803- func IncFlowControlQueueSize (fairnessID , priority , inferencePool , modelName , targetModelName string ) {
804- flowControlQueueSize .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Inc ()
881+ func IncFlowControlQueueSize (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName string ) {
882+ flowControlQueueSize .WithLabelValues (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName ).Inc ()
805883 llmdFlowControlQueueSize .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Inc ()
806884}
807885
808886// DecFlowControlQueueSize decrements the Flow Control queue size gauge.
809- func DecFlowControlQueueSize (fairnessID , priority , inferencePool , modelName , targetModelName string ) {
810- flowControlQueueSize .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Dec ()
887+ func DecFlowControlQueueSize (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName string ) {
888+ flowControlQueueSize .WithLabelValues (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName ).Dec ()
811889 llmdFlowControlQueueSize .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Dec ()
812890}
813891
814892// AddFlowControlQueueBytes increments the Flow Control queue bytes gauge.
815- func AddFlowControlQueueBytes (fairnessID , priority , inferencePool , modelName , targetModelName string , bytes uint64 ) {
816- flowControlQueueBytes .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Add (float64 (bytes ))
893+ func AddFlowControlQueueBytes (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName string , bytes uint64 ) {
894+ flowControlQueueBytes .WithLabelValues (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName ).Add (float64 (bytes ))
817895 llmdFlowControlQueueBytes .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Add (float64 (bytes ))
818896}
819897
820898// SubFlowControlQueueBytes decrements the Flow Control queue bytes gauge.
821- func SubFlowControlQueueBytes (fairnessID , priority , inferencePool , modelName , targetModelName string , bytes uint64 ) {
822- flowControlQueueBytes .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Sub (float64 (bytes ))
899+ func SubFlowControlQueueBytes (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName string , bytes uint64 ) {
900+ flowControlQueueBytes .WithLabelValues (fairnessID , priority , inferencePool , sloClass , modelName , targetModelName ).Sub (float64 (bytes ))
823901 llmdFlowControlQueueBytes .WithLabelValues (fairnessID , priority , inferencePool , modelName , targetModelName ).Sub (float64 (bytes ))
824902}
825903
0 commit comments