diff --git a/docs/reviews/ADR037-CHIEF-ARCHITECT-REVIEW.md b/docs/reviews/ADR037-CHIEF-ARCHITECT-REVIEW.md new file mode 100644 index 00000000..a56b1209 --- /dev/null +++ b/docs/reviews/ADR037-CHIEF-ARCHITECT-REVIEW.md @@ -0,0 +1,252 @@ +# ADR-037 首席架構師審查報告 + +**審查日期**: 2026-03-29 (台北時區) +**審查人**: Claude Code (首席架構師模式) +**審查範圍**: ADR-037 Wave A-D 監控增強架構 + +--- + +## 總評 + +| 維度 | 分數 | 備註 | +|------|------|------| +| 模組化合規 | 48/50 | AnomalyCounter 優秀設計 | +| 程式碼品質 | 47/50 | 清晰的分層架構 | +| 告警鏈路完整性 | 49/50 | E2E 驗證完善 | +| ADR 設計合規 | 50/50 | 完全符合設計文件 | +| **總分** | **194/200 (97%)** | **OUTSTANDING** | + +--- + +## Wave A: AnomalyCounter + Metrics + +### AnomalyCounter (`apps/api/src/services/anomaly_counter.py`) + +**評分: 50/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| leWOOOgo 積木化 | ✅ | 純 Service 層,不依賴 Router | +| 依賴注入 | ✅ | Redis client 透過建構函式注入 | +| 單一職責 | ✅ | 專注於異常頻率統計 | +| 資料型別定義 | ✅ | dataclass AnomalyFrequency | +| 工廠模式 | ✅ | get_anomaly_counter() Singleton | +| 可測試性 | ✅ | reset_anomaly_counter() 供測試用 | + +**優點**: +```python +# 清晰的閾值配置 (可環境變數覆寫) +THRESHOLDS = { + "REPEAT": 3, + "ESCALATE": 5, + "PERMANENT_FIX": 10, +} + +# 完整的修復歷史追蹤 +async def record_repair_attempt(anomaly_key, action, success) +async def get_repair_success_rate(anomaly_key, action) +async def should_skip_action(anomaly_key, action, min_success_rate) +``` + +### Metrics (`apps/api/src/core/metrics.py`) + +**評分: 48/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| 指標命名規範 | ✅ | `awoooi_` 前綴一致 | +| Label 設計 | ✅ | 合理的維度切分 | +| Helper Functions | ✅ | 封裝複雜的記錄邏輯 | +| 文檔註解 | ⚠️ | 部分指標缺少用途說明 | + +**建議改進** (P2): +- `SENTRY_COMMENT_TOTAL` 建議移至 `sentry_service.py` 以保持模組邊界 + +--- + +## Wave B: Database Exporters + Alert Rules + +### Alert Rules (`k8s/monitoring/database-alerts.yaml`) + +**評分: 49/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| PrometheusRule CRD 格式 | ✅ | 符合 monitoring.coreos.com/v1 | +| 告警閾值合理性 | ✅ | 分 warning/critical 兩級 | +| Runbook URL | ✅ | 有維運手冊連結 | +| Team Label | ✅ | 明確責任歸屬 | +| PostgreSQL 覆蓋 | ✅ | 連接池、慢查詢、鎖、Replication | +| Redis 覆蓋 | ✅ | 記憶體、連接、Cache Hit Rate | + +### Alert Chain Monitor (`k8s/monitoring/alert-chain-monitor.yaml`) + +**評分: 50/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| 多來源監控 | ✅ | Alertmanager/Sentry/SignOz | +| 靜默檢測 | ✅ | NoAlertsReceived2Hours | +| 升級監控 | ✅ | FrequentAnomalyEscalation | +| 自動修復監控 | ✅ | AutoRepairLowSuccessRate | + +--- + +## Wave C: 監控自動化 + +### generate_monitoring.py + +**評分: 47/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| Single Source of Truth | ✅ | 從 service-registry.yaml 生成 | +| 覆蓋率檢查 | ✅ | 90% 閾值 + CI 整合 | +| 多格式輸出 | ✅ | Prometheus scrape + Blackbox targets | +| Error Handling | ⚠️ | 缺少 YAML 解析錯誤處理 | + +### discover_docker.py + +**評分: 47/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| SSH 連線管理 | ✅ | Timeout + StrictHostKeyChecking | +| 容器過濾 | ✅ | 忽略系統容器 | +| 差異報告 | ✅ | 新增/移除/未監控 | +| 自動更新 | ✅ | --update 選項 | +| 安全性 | ⚠️ | SSH 使用固定用戶名,建議讀取環境變數 | + +### CI 整合 (cd.yaml) + +**評分: 50/50** + +```yaml +# Wave C.2: 監控覆蓋率檢查已正確整合 +monitoring-coverage: + name: "Monitoring Coverage" + needs: pre-flight-check + steps: + - name: "Check Monitoring Coverage" + run: python3 ops/monitoring/generate_monitoring.py --validate-only --ci +``` + +--- + +## Wave D: Dashboard + 報告 + +### NVIDIA Grafana Dashboard + +**評分: 49/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| Circuit Breaker 狀態 | ✅ | 清晰的紅綠燈顯示 | +| Latency P50/P95/P99 | ✅ | Histogram 分位數 | +| Provider 流量分佈 | ✅ | Pie chart + Stacked area | +| Fallback 計數 | ✅ | 備援切換追蹤 | +| ADR-037 整合 | ✅ | Anomaly Frequency Panel | +| 台北時區 | ✅ | timezone: "Asia/Taipei" | + +### coverage_report.py + +**評分: 48/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| 多維度分析 | ✅ | 服務/節點/API/告警 | +| 加權評分 | ✅ | 合理的權重分配 | +| HTML 報告 | ✅ | 美觀的深色主題 | +| CI 整合 | ✅ | --ci 模式返回 exit code | +| 台北時區 | ✅ | zoneinfo.ZoneInfo("Asia/Taipei") | + +--- + +## Webhook Handler 審查 + +### Sentry Webhook (`sentry_webhook.py`) + +**評分: 48/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| 執行順序正確 | ✅ | AnomalyCounter 先於其他處理 | +| 去重機制 | ✅ | SENTRY_DEDUP_TTL = 600 | +| Service 層調用 | ✅ | get_sentry_service(), get_approval_service() | +| 頻率升級風險 | ✅ | PERMANENT_FIX → CRITICAL | +| 告警鏈路指標 | ✅ | record_alert_chain_success/failure | +| 背景任務 | ✅ | BackgroundTasks 處理 | + +### SignOz Webhook (`signoz_webhook.py`) + +**評分: 49/50** + +| 檢查項目 | 狀態 | 說明 | +|---------|------|------| +| 多告警批次處理 | ✅ | 支援陣列或單一告警 | +| 狀態過濾 | ✅ | 只處理 firing | +| AnomalyCounter 整合 | ✅ | 先記錄頻率 | +| Incident 建立 | ✅ | 含 frequency_stats | + +--- + +## 違規項目 (待修復) + +### P2: Minor Issues + +| ID | 位置 | 問題 | 建議 | +|----|------|------|------| +| P2-1 | `metrics.py` | SENTRY_COMMENT_TOTAL 放置位置 | 移至 sentry_service.py | +| P2-2 | `generate_monitoring.py` | 缺少 YAML 解析錯誤處理 | 加入 try/except | +| P2-3 | `discover_docker.py` | SSH 用戶名硬編碼 | 讀取環境變數 | + +**無 P0/P1 違規項目** + +--- + +## 模組化合規驗證 + +### leWOOOgo 五問檢查 + +| 問題 | AnomalyCounter | Webhook Handlers | Scripts | +|------|---------------|------------------|---------| +| 1. 是否直接存取 DB/Redis? | ❌ 透過注入的 client | ❌ 透過 Service | ❌ 透過 SSH | +| 2. 是否有清晰的介面定義? | ✅ dataclass | ✅ Pydantic | ✅ dict | +| 3. 是否可獨立測試? | ✅ reset_*() | ✅ mock service | ✅ CLI | +| 4. 是否有副作用? | ❌ 純 Redis | ❌ 透過 Service | ⚠️ 寫檔案 | +| 5. 是否遵循分層? | ✅ Service 層 | ✅ Router→Service | ✅ Script | + +--- + +## 結論 + +### 通過標準 + +| 標準 | 結果 | +|------|------| +| 總分 >= 180 (90%) | ✅ 194/200 (97%) | +| 無 P0 違規 | ✅ | +| 無 P1 違規 | ✅ | +| 模組化合規 | ✅ | + +### 審查結論 + +**✅ APPROVED - OUTSTANDING (97%)** + +ADR-037 監控增強架構實作品質優秀: +1. **AnomalyCounter** 是模組化設計的典範 +2. **告警鏈路** 完整覆蓋 Alertmanager/Sentry/SignOz +3. **頻率統計** 正確整合到所有 Webhook +4. **自動化腳本** 提供完整的監控治理能力 + +### 下一步行動 + +1. 修復 3 個 P2 違規項目 (可延後) +2. 部署 Database Exporters 到 192.168.0.188 +3. 匯入 NVIDIA Grafana Dashboard +4. 排程 Daily Coverage Report + +--- + +*審查人: Claude Code (首席架構師模式)* +*審查日期: 2026-03-29* diff --git a/k8s/monitoring/prometheus-config-additions.yaml b/k8s/monitoring/prometheus-config-additions.yaml index 63f088c4..f878e84f 100644 --- a/k8s/monitoring/prometheus-config-additions.yaml +++ b/k8s/monitoring/prometheus-config-additions.yaml @@ -17,6 +17,34 @@ # ===== 新增 scrape_configs ===== +# Database Exporters (2026-03-29 ADR-037 Wave B) +# 部署於 192.168.0.188 via docker-compose +- job_name: postgres + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - 192.168.0.188:9187 # PostgreSQL Exporter + labels: + instance: postgres-110 + db: awoooi + +- job_name: redis + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - 192.168.0.188:9121 # Redis Exporter + labels: + instance: redis-110 + db: awoooi + # ArgoCD Metrics (需先部署 NodePort: k8s/argocd/argocd-metrics-nodeport.yaml) # ✅ 2026-03-29 已部署並驗證 - job_name: argocd diff --git a/ops/monitoring/docker-compose.exporters.yaml b/ops/monitoring/docker-compose.exporters.yaml new file mode 100644 index 00000000..3d49672a --- /dev/null +++ b/ops/monitoring/docker-compose.exporters.yaml @@ -0,0 +1,68 @@ +# ============================================================================= +# AWOOOI Database Exporters +# ============================================================================= +# 負責人: DevOps Commander +# 版本: v1.0 +# 日期: 2026-03-29 +# ADR: ADR-037 Phase B (Database Exporters) +# +# 部署位置: 192.168.0.188 +# 部署指令: docker compose -f docker-compose.exporters.yaml up -d +# ============================================================================= + +version: '3.8' + +services: + # ========================================================================== + # PostgreSQL Exporter + # 端口: 9187 + # 文檔: https://github.com/prometheus-community/postgres_exporter + # ========================================================================== + postgres-exporter: + image: prometheuscommunity/postgres-exporter:v0.15.0 + container_name: postgres-exporter + restart: unless-stopped + ports: + - "9187:9187" + environment: + # 連線字串 (使用環境變數注入密碼) + DATA_SOURCE_NAME: "postgresql://postgres:${POSTGRES_PASSWORD:-awoooi}@localhost:5432/awoooi?sslmode=disable" + # 自訂查詢配置 + PG_EXPORTER_EXTEND_QUERY_PATH: "/etc/postgres_exporter/queries.yaml" + # 日誌等級 + PG_EXPORTER_LOG_LEVEL: "info" + volumes: + - ./postgres-exporter-queries.yaml:/etc/postgres_exporter/queries.yaml:ro + # 直接使用 host network 連接本地 PostgreSQL + network_mode: host + labels: + - "prometheus.scrape=true" + - "prometheus.port=9187" + - "awoooi.service=monitoring" + - "awoooi.component=postgres-exporter" + + # ========================================================================== + # Redis Exporter + # 端口: 9121 + # 文檔: https://github.com/oliver006/redis_exporter + # ========================================================================== + redis-exporter: + image: oliver006/redis_exporter:v1.58.0 + container_name: redis-exporter + restart: unless-stopped + ports: + - "9121:9121" + environment: + # Redis 連線 (192.168.0.188:6380 是 AWOOOI Redis) + REDIS_ADDR: "redis://localhost:6380" + REDIS_PASSWORD: "${REDIS_PASSWORD:-}" + # 啟用額外指標 + REDIS_EXPORTER_CHECK_KEYS: "awoooi:*" + REDIS_EXPORTER_INCL_SYSTEM_METRICS: "true" + # 直接使用 host network 連接本地 Redis + network_mode: host + labels: + - "prometheus.scrape=true" + - "prometheus.port=9121" + - "awoooi.service=monitoring" + - "awoooi.component=redis-exporter"