Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 2m16s
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>
351 lines
11 KiB
Markdown
351 lines
11 KiB
Markdown
# 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: 30s(A1 拆分後)
|
||
│
|
||
├─ [solver] 決策建議 — 主力 Provider: openclaw_nemo
|
||
│ timeout: 20s
|
||
│
|
||
└─ [critic] 方案審核 — 主力 Provider: openclaw_nemo
|
||
timeout: 15s
|
||
```
|
||
|
||
NIM(NVIDIA 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 或 timeout:NIM 已無法使用。進行動作 2。
|
||
|
||
**動作 2:強制切換主力 Provider(緊急)**
|
||
|
||
AI Router 的 DIAGNOSE intent 已有 fallback chain(NEMO→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` 共用三段 agent,NIM 尾巴 latency 27s 命中 timeout。
|
||
**修復**:A1 拆分三段獨立 timeout(diagnostician=30s / solver=20s / critic=15s)。
|
||
**教訓**:不同 agent 的工作量不同,不應共用同一個 timeout 值。
|
||
|
||
### INC-20260425-3B6C39
|
||
|
||
**症狀**:DIAGNOSE fallback 到 Ollama(CPU-only),造成 238s 二次 timeout。
|
||
**根因**:AI Router fallback chain 含 Ollama,Ollama 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 數據再調整。
|