feat(cag): PrometheusRule + Grafana panels for KV cache observability

- cag-kv-cache-rules.yaml: recording rule vllm:prefix_cache_hit_rate
  (from cache_query_hit/miss counters), 3 alert rules:
  KVWarmupFailureHigh, KVWarmupMissHigh, VLLMPrefixCacheHitRateLow
- api-latency-dashboard.yaml: 5 new panels (id 7-11):
  prefix cache hit rate, warmup hit/miss, warmup latency p50/p95,
  standing context tier hits, alert panel with fixed threshold 0.01/s
This commit is contained in:
2026-09-27 18:37:03 +08:00
parent 920693df1b
commit 605bc706e0
3 changed files with 222 additions and 0 deletions
@@ -0,0 +1,71 @@
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: cag-kv-cache-rules
namespace: monitoring
labels:
release: prometheus
spec:
groups:
# Recording rules: derive vLLM prefix cache hit rate from raw counters
- name: vllm.recording
rules:
- record: vllm:prefix_cache_hit_rate
expr: |
rate(vllm:cache_query_hit_total[5m])
/
clamp_min(
rate(vllm:cache_query_hit_total[5m]) + rate(vllm:cache_query_miss_total[5m]),
0.001
)
labels:
job: "vllm"
# Alert rules: CAG pipeline health
- name: cag.alerts
rules:
# KV warmup consistently failing — cache never gets warm
- alert: KVWarmupFailureHigh
expr: |
rate(memory_kv_cache_warmup_error_total[5m]) > 0.01
for: 5m
labels:
severity: warning
team: poimen
annotations:
summary: "KV warmup errors elevated ({{ $value | humanize }}/s)"
description: |
The KV cache warmer is failing to reach vLLM at a rate > 0.01/s
for 5 consecutive minutes. The prefix KV cache is not being warmed;
agents will see full prefill latency on every call.
Check reasoning-predictor health and poimen-memory NetworkPolicy.
# Warmup misses: vLLM reachable but not caching
- alert: KVWarmupMissHigh
expr: |
rate(memory_kv_cache_warmup_miss_total[5m]) > 0.01
for: 5m
labels:
severity: warning
team: poimen
annotations:
summary: "KV warmup cache misses elevated ({{ $value | humanize }}/s)"
description: |
vLLM is reachable but cached_tokens=0 on warmup responses.
Possible causes: prefix caching disabled in vLLM, max-num-seqs
saturated during warmup, or context format changed.
# Prefix cache hit rate low after warmup should be established
- alert: VLLMPrefixCacheHitRateLow
expr: |
vllm:prefix_cache_hit_rate < 0.70
for: 10m
labels:
severity: warning
team: poimen
annotations:
summary: "vLLM prefix cache hit rate low ({{ $value | humanizePercentage }})"
description: |
vLLM prefix cache hit rate below 70% for 10 minutes.
Expected >= 85% in steady state with CAG warming active.
Check KVWarmupFailureHigh / KVWarmupMissHigh alerts for root cause.
+1
View File
@@ -14,6 +14,7 @@ resources:
- alerts/svc-vault-rules.yaml - alerts/svc-vault-rules.yaml
- alerts/cluster-alerts.yaml - alerts/cluster-alerts.yaml
- alerts/api-gateway-alerts.yaml - alerts/api-gateway-alerts.yaml
- alerts/cag-kv-cache-rules.yaml
- servicemonitors/argocd.yaml - servicemonitors/argocd.yaml
- servicemonitors/authentik.yaml - servicemonitors/authentik.yaml
- servicemonitors/forgejo.yaml - servicemonitors/forgejo.yaml
@@ -123,6 +123,156 @@ data:
"custom": {"fillOpacity": 10} "custom": {"fillOpacity": 10}
} }
} }
},
{
"id": 7,
"title": "vLLM Prefix Cache Hit Rate",
"type": "timeseries",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 36},
"datasource": {"type": "prometheus", "uid": "prometheus"},
"targets": [
{
"expr": "vllm:prefix_cache_hit_rate",
"legendFormat": "prefix cache hit rate"
}
],
"fieldConfig": {
"defaults": {
"unit": "percentunit",
"min": 0,
"max": 1,
"custom": {"fillOpacity": 15},
"thresholds": {
"mode": "absolute",
"steps": [
{"color": "red", "value": 0},
{"color": "yellow", "value": 0.7},
{"color": "green", "value": 0.85}
]
}
}
}
},
{
"id": 8,
"title": "KV Warmup Hit vs Miss",
"type": "timeseries",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 36},
"datasource": {"type": "prometheus", "uid": "prometheus"},
"targets": [
{
"expr": "rate(memory_kv_cache_warmup_hit_total[5m])",
"legendFormat": "warmup hit"
},
{
"expr": "rate(memory_kv_cache_warmup_miss_total[5m])",
"legendFormat": "warmup miss"
},
{
"expr": "rate(memory_kv_cache_warmup_error_total[5m])",
"legendFormat": "warmup error"
}
],
"fieldConfig": {
"defaults": {
"unit": "ops",
"custom": {"fillOpacity": 10}
}
}
},
{
"id": 9,
"title": "KV Warmup Latency p50/p95 (ms)",
"type": "timeseries",
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 44},
"datasource": {"type": "prometheus", "uid": "prometheus"},
"targets": [
{
"expr": "histogram_quantile(0.50, sum(rate(memory_kv_cache_warmup_latency_ms_bucket[5m])) by (le))",
"legendFormat": "p50 warmup latency"
},
{
"expr": "histogram_quantile(0.95, sum(rate(memory_kv_cache_warmup_latency_ms_bucket[5m])) by (le))",
"legendFormat": "p95 warmup latency"
}
],
"fieldConfig": {
"defaults": {
"unit": "ms",
"custom": {"fillOpacity": 10}
}
}
},
{
"id": 10,
"title": "Standing Context Cache Tier Hits",
"type": "timeseries",
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 44},
"datasource": {"type": "prometheus", "uid": "prometheus"},
"targets": [
{
"expr": "rate(memory_standing_ctx_hit_redis_total[5m])",
"legendFormat": "Redis L1 hit"
},
{
"expr": "rate(memory_standing_ctx_hit_db_total[5m])",
"legendFormat": "DB L2 hit"
},
{
"expr": "rate(memory_standing_ctx_recompute_total[5m])",
"legendFormat": "recompute (L3)"
},
{
"expr": "rate(memory_standing_ctx_304_total[5m])",
"legendFormat": "304 Not Modified"
}
],
"fieldConfig": {
"defaults": {
"unit": "ops",
"custom": {"fillOpacity": 10}
}
}
},
{
"id": 11,
"title": "Standing Context Alert: Stale > 10min post-ingest",
"type": "timeseries",
"description": "Alert if standing context was not refreshed within 10min of an ingest event. Indicates staleness propagation failure.",
"gridPos": {"h": 8, "w": 24, "x": 0, "y": 52},
"datasource": {"type": "prometheus", "uid": "prometheus"},
"targets": [
{
"expr": "rate(memory_standing_ctx_recompute_total[5m]) > 0",
"legendFormat": "recompute rate (non-zero = fresh)"
},
{
"expr": "rate(memory_kv_cache_warmup_miss_total[5m])",
"legendFormat": "warmup miss rate (alert if > 3/5min)"
}
],
"fieldConfig": {
"defaults": {
"unit": "ops",
"custom": {"fillOpacity": 10},
"thresholds": {
"mode": "absolute",
"steps": [
{"color": "green", "value": 0},
{"color": "red", "value": 0.01}
]
}
},
"overrides": [
{
"matcher": {"id": "byName", "options": "warmup miss rate (alert if > 3/5min)"},
"properties": [
{"id": "thresholds", "value": {"mode": "absolute", "steps": [{"color": "green", "value": 0}, {"color": "red", "value": 0.01}]}},
{"id": "custom.thresholdsStyle", "value": {"mode": "area"}}
]
}
]
}
} }
] ]
} }