Files
awoooi/docs/runbooks/RUNBOOK-AGENT-STEP-LATENCY.md
Your Name fb130c9a28
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 2m16s
feat(p3.1-t2): DiagnosisAggregator stub tests + sanitization 補強 + metrics 補欄
Wave 8 P3.1-T2 後續補測 + 配套:

新增測試:
- test_diagnosis_aggregator_stub.py (238 行) — 15 tests
  · stub fixture 驗證 _collect_diagnosis_aggregator 接線
  · feature flag default off 不呼叫
  · timeout 邊界 / exception fail-soft

修改:
- core/metrics.py +23 — 新增 DiagnosisAggregator 相關 Prometheus 指標
- sanitization_service.py +24 — 補強 prompt sanitize 邊界(vuln #4 配套)
- RUNBOOK-AGENT-STEP-LATENCY.md / agent_step_latency_rules.yaml — 微調

Tests: 15 passed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 08:30:26 +08:00

351 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RUNBOOK-AGENT-STEP-LATENCY.md
# Agent Step Latency — 診斷與處置 Runbook
# 2026-04-27 Claude Sonnet 4.6: A3 — Agent step latency observability (config A+B Wave 1)
# 對應告警規則: ops/monitoring/grafana/agent_step_latency_rules.yaml
---
## 快速索引
| 告警 | 嚴重度 | 章節 |
|------|--------|------|
| `AgentStepLatencyHigh` | warning | [#agentsteplatencyhigh](#agentsteplatencyhigh) |
| `AgentStepTimeoutSpike` | critical | [#agentsteptimeoutspike](#agentsteptimeoutspike) |
| `DiagnoseFallbackToCloud` | warning | [#diagnosefallbacktocloud](#diagnosefallbacktocloud) |
---
## 系統背景
AWOOOI Phase 2 多 Agent 協作ADR-082由三個 agent 串行處理每個 Incident
```
Incident 接收
├─ [diagnostician] 診斷分析 — 主力 Provider: openclaw_nemo (NIM @ 192.168.0.188:8088)
│ timeout: 30sA1 拆分後)
├─ [solver] 決策建議 — 主力 Provider: openclaw_nemo
│ timeout: 20s
└─ [critic] 方案審核 — 主力 Provider: openclaw_nemo
timeout: 15s
```
NIMNVIDIA Inference Microservice實測延遲**2-27s**,平均 ~10.6s。
尾巴 latency 若命中 timeout → agent 輸出 confidence=20%degraded→ 飛輪失能。
**根因案例**INC-20260425-8D17BB / INC-20260425-3B6C39
共用 `PHASE2_STEP_TIMEOUT_SEC=20.0s`NIM 27s 尾巴 latency 命中 timeout全部 Incident 落入「待分析」。
---
## 根因鏈
```mermaid
flowchart TD
A[NIM GPU 高負載 / 網路抖動] --> B[step latency 尾巴 > 20-30s]
B --> C[AgentStepLatencyHigh p75 > 25s]
B --> D[agent timeout → confidence=20%]
D --> E[AgentStepTimeoutSpike > 3/min]
D --> F[DIAGNOSE fallback chain 啟動]
F --> G[openclaw_nemo → gemini]
G --> H[DiagnoseFallbackToCloud > 5/min]
H --> I[Gemini 每日配額快速耗盡]
I --> J[gemini → claude 第二段 fallback]
J --> K[費用急升 / 飛輪完全失能]
style A fill:#ff6b6b,color:#fff
style K fill:#ff6b6b,color:#fff
style C fill:#ffd93d,color:#000
style E fill:#ff6b6b,color:#fff
style H fill:#ffd93d,color:#000
```
---
## AgentStepLatencyHigh
### 告警含義
| 欄位 | 值 |
|------|----|
| 觸發條件 | 任意 agent 的 p75 step latency > 25s持續 10 分鐘 |
| 嚴重度 | warning |
| 代表什麼 | NIM 推理尾巴偏慢,尚未 timeout但趨勢惡化 |
| 不代表什麼 | agent 還在正常運作,只是變慢 |
### 立即診斷3 步)
**步驟 1看哪個 agent 卡**
在 Grafana 查 (Prometheus 地址: `http://192.168.0.110:9090`)
```promql
histogram_quantile(
0.75,
sum by (agent, le) (
rate(aiops_agent_step_duration_seconds_bucket[5m])
)
)
```
看各 agent 的 p75 值,確認哪個 agent 最慢。
也可看 p95 了解最壞情況:
```promql
histogram_quantile(
0.95,
sum by (agent, le) (
rate(aiops_agent_step_duration_seconds_bucket[5m])
)
)
```
**步驟 2看 NIM 健康度**
```bash
# 確認 NIM API 回應時間
curl -o /dev/null -s -w "%{time_total}s\n" http://192.168.0.188:8088/v1/models
# 確認 GPU 狀態
ssh wooo@192.168.0.188 'nvidia-smi --query-gpu=utilization.gpu,memory.used,memory.total,temperature.gpu --format=csv,noheader'
```
| GPU 指標 | 正常 | 警戒 |
|----------|------|------|
| GPU 使用率 | < 80% | > 90% |
| GPU 記憶體 | < 10GB | > 11GB |
| GPU 溫度 | < 80°C | > 85°C |
**步驟 3看 provider 路由分布**
```promql
# 過去 5 分鐘各 provider 的呼叫比例
sum by (provider) (rate(ai_router_selected_provider_total[5m]))
```
`openclaw_nemo` 佔比大幅下降,代表 fallback 已在發生。
### 處置動作3 步)
**動作 1暫時調高 timeout 環境變數(緩解)**
若 NIM 只是暫時慢(< 1 小時),可調高 timeout 讓 agent 等更久:
```bash
# 確認目前設定
kubectl get deployment api -n awoooi-prod -o jsonpath='{.spec.template.spec.containers[0].env}' | python3 -m json.tool | grep -i timeout
# 暫時調高(需統帥授權才能改 ConfigMap
# 正常路徑:修改 k8s/awoooi-prod/04-configmap.yaml 中的 PHASE2_STEP_TIMEOUT_SEC
# 緊急路徑kubectl set env deployment/api -n awoooi-prod PHASE2_STEP_TIMEOUT_SEC=35
```
> ⚠️ 調高 timeout 不是根治只是緩解。timeout 太長會讓 Incident 積壓。
**動作 2確認 NIM 是否需要重啟**
```bash
# 檢查 NIM 服務狀態
ssh wooo@192.168.0.188 'docker ps --filter name=nim --format "{{.Status}}"'
# 若 NIM 容器 unhealthy重啟須確認無其他 session 在使用)
ssh wooo@192.168.0.188 'docker restart <nim_container_name>'
# 重啟後驗證
curl -s http://192.168.0.188:8088/v1/models | python3 -m json.tool
```
**動作 3升級統帥**
若 NIM 重啟無效且 latency 仍高Telegram 通知統帥:
- NIM 位置192.168.0.188:8088
- 目前 p75[從 Grafana 截圖]
- 影響範圍diagnostician/solver/critic 全部變慢
- 建議:調查 GPU 硬體問題或考慮暫時切主力 provider 至 Gemini
---
## AgentStepTimeoutSpike
### 告警含義
| 欄位 | 值 |
|------|----|
| 觸發條件 | 任意 agent timeout 速率 > 3/min持續 5 分鐘 |
| 嚴重度 | critical |
| 代表什麼 | agent 已進入 degraded 模式confidence=20%),飛輪失能 |
| 影響 | Incident 全部落入「待分析」,自動修復停擺 |
### 立即診斷3 步)
**步驟 1確認哪個 agent 在 timeout**
```promql
# 各 agent timeout 速率(/min
sum by (agent) (
rate(aiops_agent_step_duration_seconds_count{outcome="timeout"}[5m])
) * 60
```
**步驟 2確認 NIM 是否已觸發 fallback**
```promql
# NEMO → Gemini fallback 速率(/min
rate(
aiops_diagnose_fallback_total{from_provider="openclaw_nemo", to_provider="gemini"}[5m]
) * 60
```
若 fallback > 0代表 AI Router 已在切換Gemini 正在被消耗。
**步驟 3確認飛輪狀態**
```bash
# 確認積壓的 Incident
curl -s http://192.168.0.188:8088/api/v1/incidents?status=investigating | python3 -m json.tool | grep -c '"id"'
# 查 API log 確認 degraded 訊號
kubectl logs -n awoooi-prod deploy/api --tail=50 | grep -E "degraded|confidence=0.2|timeout"
```
### 處置動作3 步)
**動作 1立即確認 NIM 是否可用**
```bash
time curl -s -X POST http://192.168.0.188:8088/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"meta/llama-3.1-8b-instruct","messages":[{"role":"user","content":"ping"}],"max_tokens":10}'
```
若回應 > 30s 或 timeoutNIM 已無法使用。進行動作 2。
**動作 2強制切換主力 Provider緊急**
AI Router 的 DIAGNOSE intent 已有 fallback chainNEMO→GEMINI→CLAUDE
若需要完全跳過 NIM 嘗試,可暫時覆寫 intent override
```bash
# 緊急設定:跳過 NEMO直接走 GEMINI需統帥授權
kubectl set env deployment/api -n awoooi-prod \
DIAGNOSE_FORCE_PROVIDER=gemini \
-n awoooi-prod
```
> ⚠️ 此環境變數需 A2 代碼支援,確認 ai_router.py 是否有讀取此設定。
> 若無,請人工協調 SRE 直接修改 ConfigMap。
**動作 3升級統帥必須**
critical 告警必須在 15 分鐘內升級:
- 告警觸發時間:[從 Telegram 告警中取得]
- 受影響 agent[從步驟 1 的 Grafana 截圖]
- 積壓 Incident 數:[從步驟 3 取得]
- NIM 狀態:[可用/timeout/離線]
---
## DiagnoseFallbackToCloud
### 告警含義
| 欄位 | 值 |
|------|----|
| 觸發條件 | NEMO→Gemini fallback > 5/min持續 5 分鐘 |
| 嚴重度 | warning |
| 代表什麼 | NIM 無法服務Gemini 正在消耗每日配額 |
| 風險 | Gemini 配額耗盡後 fallback 到 Claude費用更高或完全失敗 |
### 立即診斷3 步)
**步驟 1查目前 fallback 速率與累積數**
```promql
# 當前 fallback 速率(/min
rate(
aiops_diagnose_fallback_total{from_provider="openclaw_nemo", to_provider="gemini"}[5m]
) * 60
# 今日累積 fallback 次數Counter 累積值)
aiops_diagnose_fallback_total{from_provider="openclaw_nemo", to_provider="gemini"}
```
**步驟 2查 NIM 健康度**
`AgentStepLatencyHigh` 步驟 2`nvidia-smi` + NIM API 回應測試)。
**步驟 3確認 Gemini 今日配額剩餘**
```promql
# Gemini 配額使用率
gemini_daily_call_count / gemini_daily_quota
```
若比率 > 0.8`GeminiQuotaApproaching` 告警即將觸發,需立即決定是否限流。
### 處置動作3 步)
**動作 1確認 fallback 是否必要NIM 真的掛了?)**
```bash
# 快速健康測試
curl -s --max-time 5 http://192.168.0.188:8088/v1/models
```
若 NIM 可用(回應 < 5s可能是短暫抖動觀察 5 分鐘是否自動恢復。
若 NIM 不可用fallback 是正確行為,轉入動作 2 管理配額。
**動作 2估算 Gemini 配額剩餘時間**
```
剩餘配額 = gemini_daily_quota - gemini_daily_call_count從 Prometheus 讀取)
當前消耗速率 = 從 DiagnoseFallbackToCloud 告警值(/min
預估耗盡時間 = 剩餘配額 / 當前速率(分鐘)
```
若預估耗盡時間 < 2 小時:升級統帥,考慮暫停部分 Incident 自動處理。
**動作 3升級統帥若配額不足**
提供以下資訊:
- Gemini 配額使用率:[從 Prometheus 讀取]
- 預估耗盡時間:[計算結果]
- NIM 狀態:[離線/慢速/已恢復]
- 建議:修復 NIM 或增加 Gemini 配額
---
## 根因案例參照
### INC-20260425-8D17BB
**症狀**Diagnostician 信心持續降至 20%,所有 Incident 輸出「待分析」。
**根因**`PHASE2_STEP_TIMEOUT_SEC=20s` 共用三段 agentNIM 尾巴 latency 27s 命中 timeout。
**修復**A1 拆分三段獨立 timeoutdiagnostician=30s / solver=20s / critic=15s
**教訓**:不同 agent 的工作量不同,不應共用同一個 timeout 值。
### INC-20260425-3B6C39
**症狀**DIAGNOSE fallback 到 OllamaCPU-only造成 238s 二次 timeout。
**根因**AI Router fallback chain 含 OllamaOllama CPU 推理 238s 完全不可用。
**修復**A2 將 Ollama 永久移出 `_diagnose_fallback_chain`NEMO→GEMINI→CLAUDE
**教訓**fallback chain 的每個節點必須有實測延遲數據,不能假設可用。
---
## 待校準項目
> 以下門檻在 A1/A2 上線後,應根據實際 metric 重新校準。
> 目前使用 INC-20260425 實測數據NIM 2-27s估算。
| 告警 | 目前門檻 | 校準方式 |
|------|----------|----------|
| `AgentStepLatencyHigh` | p75 > 25s | 觀察 7d p75 基線,設為基線 × 1.5 |
| `AgentStepTimeoutSpike` | > 3/min | 觀察正常日的 timeout 率,應接近 0 |
| `DiagnoseFallbackToCloud` | > 5/min | 觀察 NIM 重啟時的 spike 幅度,設為 spike 的 30% |
校準時機A1+A2 上線後,收集 **7 天**的 metric 數據再調整。