# ADR-022: Sentry 整合架構

| 項目 | 內容 |
|------|------|
| **狀態** | ✅ 已採用 |
| **日期** | 2026-03-26 |
| **決策者** | 首席架構師 + 統帥 |
| **Phase** | Phase 10 |

## 背景

AWOOOI 需要完整的錯誤追蹤能力，補強 SignOz APM 的不足：
- SignOz 專注效能監控 (Traces, Metrics)
- Sentry 專注錯誤追蹤 (Stacktrace, Context, Session Replay)

## 決策

採用 **BFF + AI 分析** 三層架構：

```
┌─────────────────────────────────────────────────────────────┐
│                    AWOOOI Web UI                            │
│         /errors 頁面 (React + next-intl)                    │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  AWOOOI API (BFF Layer)                     │
│         Router: /api/v1/errors/*                            │
│         Service: SentryService + ErrorAnalyzerService       │
└─────────────────────────────────────────────────────────────┘
                              │
              ┌───────────────┼───────────────┐
              ▼                               ▼
┌──────────────────────┐         ┌──────────────────────────┐
│   Sentry Self-Hosted │         │   OpenClaw LLM           │
│   192.168.0.110:9000 │         │   192.168.0.188:8088     │
└──────────────────────┘         └──────────────────────────┘
```

## 架構組件

### 1. SentryService (`services/sentry_service.py`)

**職責**: 封裝 Sentry API 呼叫

```python
class SentryService:
    async def list_projects() -> list[dict]
    async def list_issues(query, limit, cursor) -> list[dict]
    async def get_issue(issue_id) -> dict
    async def get_issue_events(issue_id, limit, full) -> list[dict]
    async def get_project_stats(stat, resolution) -> list
    def get_issue_url(issue_id) -> str
```

**設計原則**:
- Singleton 模式
- 配置從 `core/config.py` Settings 取得
- 支援 DI 測試替換

### 2. ErrorAnalyzerService (`services/error_analyzer_service.py`)

**職責**: AI 根因分析

```python
class ErrorAnalyzerService:
    async def analyze_error(
        issue_id, title, level, culprit,
        count, stacktrace, context
    ) -> tuple[ErrorAnalysisResult | None, str, bool]
```

**分析結果**:
- root_cause: 根因分析
- category: CODE_BUG | DEPENDENCY | CONFIGURATION | ...
- severity: LOW | MEDIUM | HIGH | CRITICAL
- fix_recommendation: 修復建議
- prevention: 預防措施
- confidence: 信心度 (0.0-1.0)

### 3. Router Layer (`api/v1/errors.py`)

**職責**: HTTP 轉發 (符合 leWOOOgo 積木化)

| 端點 | 功能 |
|------|------|
| `GET /stats` | 錯誤統計概覽 |
| `GET /issues` | 列出 Issues (分頁、過濾) |
| `GET /issues/{id}` | Issue 詳情 |
| `GET /trends` | 趨勢圖表數據 |
| `POST /issues/{id}/analyze` | 觸發 AI 分析 |

## 配置管理

所有 Sentry 配置集中於 `core/config.py`:

```python
SENTRY_SELF_HOSTED_URL: str = "http://192.168.0.110:9000"
SENTRY_ORG: str = "sentry"
SENTRY_PROJECT: str = "awoooi-api"
SENTRY_AUTH_TOKEN: str = ""  # K8s Secret
```

## 與 SignOz 的關係

| 工具 | 職責 | 查看時機 |
|------|------|----------|
| **SignOz** | APM + Traces | 慢、效能問題 |
| **Sentry** | Error Tracking | 壞、錯誤堆疊 |

**互補策略**: 兩者皆部署，各司其職。

## 前端整合

- 使用 `next-intl` 100% i18n (禁止 hardcode)
- Nothing.tech 視覺規範 (白底、細邊框、無陰影)
- React Hook: `useErrors()` 自動刷新 60 秒

## 替代方案 (已拒絕)

| 方案 | 拒絕原因 |
|------|----------|
| 直接嵌入 Sentry Iframe | 違反視覺主權，無法自訂 UI |
| 前端直接呼叫 Sentry API | 違反 BFF 原則，CORS 問題 |
| 只用 SignOz | 錯誤追蹤能力不足 |

## 後果

### 正面
- 完整的錯誤追蹤能力
- AI 輔助根因分析
- 符合 leWOOOgo 架構

### 負面
- 多一個服務需維護 (Sentry Self-Hosted)
- 額外的 API 呼叫延遲

## 🔴 前端內網 IP 禁令 (2026-03-30 補充)

### 問題

前端 Sentry DSN 使用內網 IP (`192.168.0.110:9000`) 會觸發瀏覽器「存取區域網路」權限對話框。

### 解決方案

**已採用**: Sentry Tunnel (方案 A)

```
前端 → /api/sentry-tunnel → Sentry Server (192.168.0.110:9000)
          ↑ 公網域名            ↑ Server-Side 內網
```

**配置位置**:
- `apps/web/src/app/api/sentry-tunnel/route.ts` - Tunnel 實作
- `apps/web/sentry.client.config.ts` - `tunnel: '/api/sentry-tunnel'`

### CD Pipeline 規範

```yaml
# ❌ 禁止 (即使有 Tunnel，也不應暴露內網 IP)
--build-arg NEXT_PUBLIC_SENTRY_DSN=http://...@192.168.0.110:9000/2

# ✅ 不設定 (依賴 Tunnel 機制)
# 或使用公網域名反向代理
```

## 相關文件

- `project_phase10_arch_review.md` - 架構審查報告
- `project_sentry_full_integration.md` - 整合計畫
- `feedback_sentry_local_network.md` - 區域網路權限問題
- ADR-005: BFF Architecture
- ADR-006: AI Fallback Strategy
