Skip to content

Metrics

This guide describes the current state of exposed metrics and how to scrape them.

Requirements

To have response metrics, ensure the body mode is set to Buffered or Streamed (this should be the default behavior for all implementations).

If you want to include usage metrics for vLLM model server streaming request, send the request with include_usage:

curl -i ${IP}:${PORT}/v1/completions -H 'Content-Type: application/json' -d '{
"model": "food-review",
"prompt": "whats your fav movie?",
"max_tokens": 10,
"temperature": 0,
"stream": true,
"stream_options": {"include_usage": "true"}
}'

To have response metrics, ensure the vLLM model server is configured with the dynamic LoRA adapter as a sidecar container and a ConfigMap to configure which models to load/unload. See this doc for an example.

Exposed metrics

EPP

Metric name Metric Type
Description
Labels
Status
inference_model_request_total Counter The counter of requests broken out for each model. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_request_error_total Counter The counter of requests errors broken out for each model. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_request_duration_seconds Distribution Distribution of response latency. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
normalized_time_per_output_token_seconds Distribution Distribution of ntpot (response latency per output token) model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_request_sizes Distribution Distribution of request size in bytes. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_response_sizes Distribution Distribution of response size in bytes. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_input_tokens Distribution Distribution of input token count. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_output_tokens Distribution Distribution of output token count. model_name=<model-name>
target_model_name=<target-model-name>
ALPHA
inference_model_running_requests Gauge Number of running requests for each model. model_name=<model-name> ALPHA
inference_pool_average_kv_cache_utilization Gauge The average kv cache utilization for an inference server pool. name=<inference-pool-name> ALPHA
inference_pool_average_queue_size Gauge The average number of requests pending in the model server queue. name=<inference-pool-name> ALPHA
inference_pool_per_pod_queue_size Gauge The total number of queue for each model server pod under the inference pool model_server_pod=<model-server-pod-name>
name=<inference-pool-name>
ALPHA
inference_pool_ready_pods Gauge The number of ready pods for an inference server pool. name=<inference-pool-name> ALPHA
inference_extension_info Gauge The general information of the current build. commit=<hash-of-the-build>
build_ref=<ref-to-the-build>
ALPHA

Dynamic LoRA Adapter Sidecar

Metric name Metric Type
Description
Labels
Status
lora_syncer_adapter_status Gauge Status of LoRA adapters (1=loaded, 0=not_loaded) adapter_name=<adapter-id> ALPHA

Scrape Metrics

The metrics endpoints are exposed on different ports by default:

  • EPP exposes the metrics endpoint at port 9090
  • Dynamic LoRA adapter sidecar exposes the metrics endpoint at port 8080

To scrape metrics, the client needs a ClusterRole with the following rule: nonResourceURLs: "/metrics", verbs: get.

Here is one example if the client needs to mound the secret to act as the service account

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: inference-gateway-metrics-reader
rules:
- nonResourceURLs:
  - /metrics
  verbs:
  - get
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: inference-gateway-sa-metrics-reader
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: inference-gateway-sa-metrics-reader-role-binding
  namespace: default
subjects:
- kind: ServiceAccount
  name: inference-gateway-sa-metrics-reader
  namespace: default
roleRef:
  kind: ClusterRole
  name: inference-gateway-metrics-reader
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: Secret
metadata:
  name: inference-gateway-sa-metrics-reader-secret
  namespace: default
  annotations:
    kubernetes.io/service-account.name: inference-gateway-sa-metrics-reader
type: kubernetes.io/service-account-token

Then, you can curl the appropriate port as follows. For EPP (port 9090)

TOKEN=$(kubectl -n default get secret inference-gateway-sa-metrics-reader-secret  -o jsonpath='{.secrets[0].name}' -o jsonpath='{.data.token}' | base64 --decode)

kubectl -n default port-forward inference-gateway-ext-proc-pod-name  9090

curl -H "Authorization: Bearer $TOKEN" localhost:9090/metrics

Prometheus Alerts

The section instructs how to configure prometheus alerts using collected metrics.

Configure alerts

You can follow this blog post for instruction of setting up alerts in your monitoring stacks with Prometheus.

A template alert rule is available at alert.yaml. You can modify and append these rules to your existing Prometheus deployment.

High Inference Request Latency P99

alert: HighInferenceRequestLatencyP99
expr: histogram_quantile(0.99, rate(inference_model_request_duration_seconds_bucket[5m])) > 10.0 # Adjust threshold as needed (e.g., 10.0 seconds)
for: 5m
annotations:
  title: 'High latency (P99) for model {{ $labels.model_name }}'
  description: 'The 99th percentile request duration for model {{ $labels.model_name }} and target model {{ $labels.target_model_name }} has been consistently above 10.0 seconds for 5 minutes.'
labels:
  severity: 'warning'

High Inference Error Rate

alert: HighInferenceErrorRate
expr: sum by (model_name) (rate(inference_model_request_error_total[5m])) / sum by (model_name) (rate(inference_model_request_total[5m])) > 0.05 # Adjust threshold as needed (e.g., 5% error rate)
for: 5m
annotations:
  title: 'High error rate for model {{ $labels.model_name }}'
  description: 'The error rate for model {{ $labels.model_name }} and target model {{ $labels.target_model_name }} has been consistently above 5% for 5 minutes.'
labels:
  severity: 'critical'
  impact: 'availability'

High Inference Pool Queue Average Size

alert: HighInferencePoolAvgQueueSize
expr: inference_pool_average_queue_size > 50 # Adjust threshold based on expected queue size
for: 5m
annotations:
  title: 'High average queue size for inference pool {{ $labels.name }}'
  description: 'The average number of requests pending in the queue for inference pool {{ $labels.name }} has been consistently above 50 for 5 minutes.'
labels:
  severity: 'critical'
  impact: 'performance'

High Inference Pool Average KV Cache

alert: HighInferencePoolAvgKVCacheUtilization
expr: inference_pool_average_kv_cache_utilization > 0.9 # 90% utilization
for: 5m
annotations:
  title: 'High KV cache utilization for inference pool {{ $labels.name }}'
  description: 'The average KV cache utilization for inference pool {{ $labels.name }} has been consistently above 90% for 5 minutes, indicating potential resource exhaustion.'
labels:
  severity: 'critical'
  impact: 'resource_exhaustion'