# RunBook: Phase E — SignOz Webhook Handler 生產部署

> **類型**: 操作型 RunBook  
> **優先級**: 🔴 P0  
> **建立**: 2026-03-29 12:35 (台北)  
> **建立者**: Antigravity  
> **工時預估**: 1.5–2 小時  
> **前置條件**: SignOz UI 可在 http://192.168.0.188:3301 正常訪問

---

## 背景與現況

### 🔍 精確現況診斷

```
signoz_webhook.py    → 完整實作 (363 行，含 4 步驟完整流程)
main.py:419          → 已正確路由 include_router(signoz_webhook_v1.router)
端點：POST /api/v1/webhooks/signoz/alert   ✅ 已可接收
問題：SignOz 告警規則未指向此 Webhook
```

**唯一阻塞點**：SignOz 告警規則 (`ops/signoz/alerting/rules.yaml`) 的 `webhook` 欄位尚未設定或未部署到 SignOz 主機。

### 完整資料流

```
SignOz 偵測到異常 (Error Rate / Latency / No Traces)
    ↓
SignOz Alert Manager 觸發告警
    ↓
POST http://192.168.0.120:32334/api/v1/webhooks/signoz/alert   ← 需要配置
    ↓
process_signoz_alert() [Background Task]
    ↓
├── AnomalyCounter 記錄頻率 (ADR-037) ✅
├── IncidentService 建立事件            ✅
├── ApprovalService 建立簽核            ✅
└── TelegramGateway 發送通知            ✅
```

---

## Step 1: 確認 API 端點可達

```bash
# 從 188 主機測試 SignOz Webhook 端點
curl -s http://192.168.0.120:32334/api/v1/webhooks/signoz/health
# 預期：{"status": "ok", "service": "signoz-webhook", "timestamp": "..."}

# 如端點不通，確認 Pod 狀態
kubectl get pod -n awoooi-prod -l app=awoooi-api
```

---

## Step 2: 設定 SignOz 告警規則

### 2.1 確認 ops/signoz/alerting/rules.yaml 已建立

```bash
# 確認檔案存在
ls /Users/ogt/awoooi/ops/signoz/alerting/
# 如不存在，從 IMPLEMENTATION_STEPS_REMAINING_PHASES.md 的 Phase E 代碼複製
```

### 2.2 部署告警規則到 SignOz 主機

```bash
# 登入 SignOz 主機
ssh root@192.168.0.188

# 確認 SignOz 告警配置目錄
docker inspect signoz-query-service | grep -A5 "Mounts"
# 常見路徑：/opt/signoz/config/ 或 /data/signoz/

# 複製告警規則（從本機）
# 先在本機執行：
scp /Users/ogt/awoooi/ops/signoz/alerting/rules.yaml \
    root@192.168.0.188:/opt/signoz/config/alerting/

# 在 188 主機重啟 SignOz Alert Manager（不重啟整個 SignOz）
docker restart signoz-alert-manager 2>/dev/null || \
  docker restart signoz   # 若是單容器部署
```

### 2.3 透過 SignOz API 驗證規則載入

```bash
# 在 188 主機執行
curl -s http://localhost:3301/api/v3/alerts/rules | python3 -m json.tool | head -40
# 預期看到 APIHighErrorRate, APIHighLatencyP99 等規則名稱
```

---

## Step 3: 設定 SignOz Webhook Channel

SignOz 告警通知支援 Webhook Channel，需要透過 SignOz Web UI 或 API 設定。

### 3.1 透過 SignOz UI 設定（推薦）

```
瀏覽器開啟：http://192.168.0.188:3301
路徑：Settings → Alert Channels → New Channel

類型：Webhook
名稱：AWOOOI-API
URL：http://192.168.0.120:32334/api/v1/webhooks/signoz/alert
Send resolved notifications：☑ (可選)
```

### 3.2 透過 API 設定（腳本化）

```bash
# 在 188 主機執行
curl -s -X POST http://localhost:3301/api/v1/channels \
  -H "Content-Type: application/json" \
  -d '{
    "name": "AWOOOI-API",
    "type": "webhook",
    "data": {
      "webhook_url": "http://192.168.0.120:32334/api/v1/webhooks/signoz/alert"
    }
  }'
# 預期返回 channel ID
```

---

## Step 4: 建立測試告警規則

為了驗證整個鏈路，建立一個低閾值測試規則：

```bash
# 在 188 主機的 SignOz 目錄建立測試規則
cat > /tmp/test-alert.yaml << 'EOF'
groups:
  - name: e2e_test
    rules:
      - alert: AWOOOI_E2E_SMOKE_TEST
        expr: up{job="awoooi-api"} == 1  # 永遠觸發（API 存活時）
        for: 1m
        labels:
          severity: info
          source: signoz
          test: "true"
        annotations:
          summary: "E2E Smoke Test - 請忽略"
          description: "這是 AWOOOI 告警鏈路的自動測試"
          webhook: "http://192.168.0.120:32334/api/v1/webhooks/signoz/alert"
EOF
```

---

## Step 5: 端到端驗證

### 5.1 手動觸發測試

```bash
# 直接向 AWOOOI API 發送模擬 SignOz 告警
curl -s -X POST http://192.168.0.120:32334/api/v1/webhooks/signoz/alert \
  -H "Content-Type: application/json" \
  -d '{
    "alertname": "APIHighErrorRate",
    "status": "firing",
    "labels": {
      "alertname": "APIHighErrorRate",
      "severity": "critical",
      "service_name": "awoooi-api",
      "source": "signoz"
    },
    "annotations": {
      "summary": "API 錯誤率 > 5%",
      "description": "服務 awoooi-api 錯誤率超標，這是一個測試告警"
    },
    "startsAt": "2026-03-29T12:00:00Z"
  }'

# 預期回應
# {"status": "ok", "processed": 1, "results": [{"status": "accepted", "alert_name": "APIHighErrorRate"}]}
```

### 5.2 確認 Telegram 收到告警

```
預期在 Telegram Bot 中收到：
═══════════════════════════
📊 SignOz: APIHighErrorRate
═══════════════════════════
服務：awoooi-api
摘要：API 錯誤率 > 5%
[ Y 確認 ] [ N 忽略 ]
```

### 5.3 確認 API 日誌

```bash
kubectl logs -n awoooi-prod \
  $(kubectl get pod -n awoooi-prod -l app=awoooi-api -o name | head -1) \
  --tail=30 | grep -i signoz

# 預期看到：
# signoz_alert_received   payload=...
# signoz_anomaly_recorded alert_name=APIHighErrorRate
# signoz_alert_processed  alert_name=APIHighErrorRate  incident_id=xxx
# signoz_telegram_sent    approval_id=xxx
```

---

## 驗收標準

| 項目 | 通過條件 |
|------|---------|
| Webhook 端點可達 | `curl .../signoz/health` 返回 200 |
| SignOz 規則載入 | `/api/v3/alerts/rules` 包含 `APIHighErrorRate` |
| 手動測試正常 | 回應 `{"status": "ok"}` |
| Telegram 通知 | 成功收到告警卡片 |
| Incident 建立 | DB 中可查到 `source=signoz` 的 Incident |
| Approval 建立 | `GET /api/v1/approvals` 顯示新 Approval |

---

## 常見問題排除

| 症狀 | 診斷 | 解法 |
|------|------|------|
| Webhook 404 | `curl .../signoz/health` | 確認主機是 32334 而非 8089 |
| SignOz 規則不觸發 | SignOz UI → Alerts 頁 | 確認 Prometheus 端點可抓到 awoooi-api metrics |
| Telegram 未收到 | 查 API 日誌 | 確認 `OPENCLAW_TG_BOT_TOKEN` Secret 已注入 |
| Incident 建立失敗 | 查 API 日誌 `incident_creation_failed` | 確認 PostgreSQL 連線正常 |
