Files
awoooi/docs/adr/ADR-064-alert-rule-engine-yaml-driven.md
OG T 428e66c111
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled
fix(arch-review): 首席架構師審查 S1×3 S2×3 S3×3 全修復 + ADR-064
S1 Critical:
- S1-1: asyncio 觸發移至 _call_with_fallback async 上下文,移除 sync 中的 get_event_loop()
- S1-2: _append_rule_to_yaml 加 textwrap.dedent() 正規化 LLM 輸出縮排
- S1-3: _matches() 對 alertname=["*"] 直接回傳 False,防意外命中

S2 Major:
- S2-1: auto_generate_rule() 改為 DI 參數注入 (ollama_url/model/gemini_api_key),移除 import settings
- S2-4: _generate_mock_response docstring 澄清為規則引擎生產路徑,非假數據
- S2-5: suggested_action .strip() 防空白字串繞過 or

S3 Minor:
- S3-2: priority 上界 min(next, 890)
- S3-3: alertname sanitize re.sub([{}]) 防 format KeyError
- S3-4: model_registry.py 最後修改時間戳更新

文件:
- ADR-064: Alert Rule Engine YAML 驅動 + AI 自動學習
- Skills 02: 告警規則引擎 DI 規範 + asyncio 禁止事項
- Skills 03: _generate_mock_response 語意澄清 + 規則引擎降級流程
- LOGBOOK: 本次 Session 完整記錄

2026-04-09 ogt: 首席架構師審查修正

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 10:52:40 +08:00

103 lines
3.5 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.
# ADR-064: Alert Rule Engine — YAML 驅動規則匹配 + AI 自動學習
**狀態**: 已批准
**日期**: 2026-04-09
**作者**: ogt + Claude Sonnet 4.6
**審查**: 首席架構師2026-04-09
---
## 背景
`openclaw.py` 中的 `_generate_mock_response` 用硬編碼 if/elif 實作規則匹配,每次新增告警類型都要改 Python 代碼並重新部署。隨著監控目標增加,此模式不可持續。
## 決策
### D1: 規則外化為 YAML`apps/api/alert_rules.yaml`
規則引擎從 YAML 檔載入Pod 重啟即生效,不需要改代碼。
**規則結構**:
```yaml
rules:
- id: docker_container_unhealthy
priority: 10
match:
alertname: [DockerContainerUnhealthy]
message: [unhealthy]
response:
kubectl_command: "ssh {host} 'docker inspect {container}...'"
suggested_action: RESTART_DEPLOYMENT
risk: medium
responsibility: INFRA
```
**Priority 體系**:
| 範圍 | 用途 |
|------|------|
| 1499 | 手寫規則(高優先,不被 AI 覆蓋) |
| 500890 | AI 自動生成規則 |
| 999 | `generic_fallback` 通用兜底 |
### D2: AI 自動規則學習機制
當告警命中 `generic_fallback` 時,觸發 `auto_generate_rule()`
1. 呼叫 Ollama (deepseek-r1:14b) 生成 YAML 規則片段
2. Ollama 失敗 → Gemini 2.0 Flash 備援
3. 驗證格式id/match/response/kubectl_command 必填)
4. `textwrap.dedent()` 正規化縮排(防 LLM 輸出前置空格)
5. append 到 `alert_rules.yaml`
6. `lru_cache.cache_clear()` — 同 Pod 立即生效
### D3: 模組邊界
- `alert_rule_engine.py` = Service 層,只讀 YAML不直接存取 Redis/DB
- `auto_generate_rule()` 採用 DI 參數注入(`ollama_url`, `model`, `gemini_api_key`),不 import settings 全域單例
- asyncio 觸發在上層 async `_call_with_fallback()` 執行,不在 sync `_generate_mock_response()` 中操作 event loop
### D4: 匹配邏輯
優先順序alertname 完全匹配 > alert_type 部分匹配 > message 關鍵字
`generic_fallback``alertname: ["*"]`)在 `_matches()` 中永遠回傳 False`match_rule()` 的第二輪迴圈單獨選取,防止其 alert_type/message 關鍵字意外命中。
## 已知限制
### L1: 多 Pod 環境下規則可能重複生成
`_generating` set 是進程記憶體級去重,多 Pod 各自維護。同一告警可能在不同 Pod 同時觸發生成,產生重複規則 append。
**緩解**: `_rule_id_exists()` 提供二次去重,但有 lru_cache 的時間窗口 race condition。
**計劃**: 若未來 Pod 數 > 2需 Redis 分散式鎖。目前 prod 為 2 Pod可接受。
### L2: `lru_cache` 跨 Pod 不同步
新規則寫入後,只有寫入的 Pod 清除了 cache其他 Pod 需重啟才能載入新規則。這是已知行為,下次告警觸發時仍會走 `generic_fallback`,但不會再次生成(`_rule_id_exists` 讀 YAML 直接確認)。
## 測試策略
`auto_generate_rule()` 採 DI可在不啟動 FastAPI 的情況下單獨測試:
```python
await auto_generate_rule(
alert_context={"labels": {"alertname": "TestAlert"}},
ollama_url="http://mock",
model="test-model",
)
```
## 相關檔案
- `apps/api/alert_rules.yaml` — 規則定義
- `apps/api/src/services/alert_rule_engine.py` — 規則引擎
- `apps/api/src/services/openclaw.py``_generate_mock_response` + `_call_with_fallback` 整合點
- `apps/api/Dockerfile` — COPY alert_rules.yaml
## 參考
- ADR-006: AI 模型路由配置
- ADR-052: Phase 24 AIRouter
- `feedback_lewooogo_modular_enforcement.md`: 積木化 5 問