docs(plan): Sprint 5 指令中心重設計 — 完整解決方案與細化實施步驟

This commit is contained in:
OG T
2026-04-08 12:01:14 +08:00
parent 876aa9a441
commit f2b3a7129f

View File

@@ -0,0 +1,532 @@
# Sprint 5 — 指令中心重設計:完整解決方案與細化實施步驟
> **建立**: 2026-04-08 (台北)
> **建立者**: Claude Code
> **狀態**: 📋 待統帥審核
> **技術選型**: ADR-060 React Flow + elkjs (已批准)
---
## 第一章:問題定義
### 1.1 現況問題
| 問題 | 具體描述 |
|------|---------|
| 首頁缺乏全局視角 | 目前首頁只有 Metrics Strip + Incident Feed + OpenClaw Panel無法一眼看清服務依賴關係 |
| 拓撲圖不存在 | `/topology` 頁面只有簡單的 host list沒有視覺化依賴圖 |
| 告警缺乏上下文 | 告警卡片不知道「這個服務影響了誰」 |
| AI 介入不透明 | 使用者不知道 OpenClaw 正在分析哪個服務 |
| 監控規模已達 67 實體 | 未來 120-150+,需要分層/聚焦能力 |
### 1.2 目標使用者
| 角色 | 使用場景 | 需要看到什麼 |
|------|---------|-------------|
| **統帥 (CIO)** | 每日巡檢、異常時指揮 | 全局健康度 → 異常在哪 → 該批准什麼 |
| **值班 SRE** | 告警響應、修復執行 | 哪個服務掛了 → 影響範圍 → 修復動作 |
| **管理層** | 週報/月報、ROI 評估 | 自動化率、MTTR 趨勢、處置分佈 |
### 1.3 成功標準
| 標準 | 量化目標 |
|------|---------|
| 發現異常 | 打開首頁 3 秒內能定位問題服務 |
| 理解影響 | 不用切換頁面就能看到依賴關係和爆炸半徑 |
| 執行修復 | 從發現到批准修復不超過 2 次點擊 |
| 資訊密度 | 一屏能呈現全局狀態,不需要捲動 |
---
## 第二章:解決方案概述
### 2.1 核心設計理念
**從「被動儀表板」到「主動指揮中心」**
```
傳統儀表板: 看數據 → 人腦判斷 → 手動操作
指令中心: 看全局 → AI 提供上下文 → 一鍵批准
```
### 2.2 頁面結構 (基於統帥截圖概念)
```
┌──────────────────────────────────────────────────────────┐
│ Header (68px): Logo + 頁面標題 + AI 狀態膠囊 + 語系 │
├──────────┬───────────────────────┬───────────────────────┤
│ Sidebar │ KPI Strip (4-5 指標) │ │
│ (224px) ├───────────────────────┤ 右側面板 (300px) │
│ │ │ ┌─────────────────┐ │
│ · 儀表板 │ 神經拓撲圖 │ │ 待核准任務 │ │
│ · 警報 │ (React Flow + elkjs) │ │ SSH URI + 按鈕 │ │
│ · 自動修復│ 嵌套群組/展開/收合 │ ├─────────────────┤ │
│ · 神經指揮│ │ │ 處置統計 │ │
│ · 腳本庫 │ │ │ 四色計數+堆疊條 │ │
│ · 知識庫 ├───────────────────────┤ └─────────────────┘ │
│ · 報表 │ 系統活動串流 (Live) │ │
│ · 審計 │ AI 推理過程時間軸 │ │
│ · 設定 ├───────────────────────┤ │
│ │ 控制列 (頻率/數據流) │ │
└──────────┴───────────────────────┴───────────────────────┘
```
### 2.3 五大區塊定義
| 區塊 | 位置 | 功能 | 資料來源 (API) |
|------|------|------|---------------|
| **KPI Strip** | 頂部橫條 | 系統健康度/活動事件/自動修復率/總操作 | `/dashboard` + `/stats/disposition` |
| **神經拓撲圖** | 中央主區域 | 服務依賴 + AI 介入 + 嵌套群組 | `/dashboard` (hosts/services) |
| **活動串流** | 中央下方 | 即時事件時間軸 (告警/AI/修復) | SSE `/events` |
| **待核准面板** | 右上 | SSH URI + 風險等級 + 批准/拒絕 | `/approvals/pending` |
| **處置統計** | 右下 | 四色計數 + 堆疊條 + 自動化率 | `/stats/disposition` |
---
## 第三章:拓撲圖詳細設計
### 3.1 嵌套群組結構
```
Level 0 (Macro View) — 預設顯示4-6 個群組節點
├── 基礎設施 (.110) [藍色邊框]
│ └── 收合時顯示: "5 服務 · 全部健康"
├── AI/數據中心 (.188) [紅色邊框 if 異常]
│ └── 收合時顯示: "10 服務 · 1 警告"
├── K3s 叢集 (120/121) [紫色邊框]
│ └── 收合時顯示: "15 Pods · 全部運行"
└── 外部網路 [橘色邊框]
└── 收合時顯示: "6 目標 · 全部可達"
Level 1 (Drill-down) — 點擊群組展開
├── .110 展開後:
│ ├── Gitea (3001) ── 健康
│ ├── Harbor (5000) ── 健康
│ ├── Sentry (9000) ── 健康
│ ├── Prometheus (9090) ── 健康
│ ├── Alertmanager (9093) ── 健康
│ └── Grafana ── 健康
├── .188 展開後:
│ ├── PostgreSQL (5432) ── 健康
│ ├── Redis (6380) ── 健康
│ ├── OpenClaw (8089) ── [AI 診斷中 ⚡]
│ ├── Ollama (11434) ── 健康
│ ├── SignOz (3301) ── 健康
│ ├── ClickHouse (8123) ── 健康
│ ├── MinIO (9000) ── 健康
│ └── Langfuse (3100) ── 健康
...
```
### 3.2 節點設計 (React Flow Custom Node)
```
┌─────────────────────────┐
│ ● healthy │ ← 狀態燈 + 文字
│ PostgreSQL │ ← 服務名稱 (Inter 600)
│ .188:5432 · Docker │ ← 位置 + 類型 (JetBrains Mono 9px)
└─────────────────────────┘
圓角 8px · 0.5px 邊框 · card shadow
狀態顏色:
● 綠色 (#22C55E) = healthy
● 橘色 (#F59E0B) = warning (CPU/Memory 偏高)
● 紅色 (#cc2200) = critical (服務不可用)
● 藍色 (#4A90D9) = AI 正在診斷
● 灰色 (#A3A3A3) = unknown
```
### 3.3 邊線設計
| 類型 | 樣式 | 用途 |
|------|------|------|
| 正常依賴 | 綠色漸層 → 透明,實線 | 健康的服務間連線 |
| 異常依賴 | 橘色→紅色漸層,虛線 | 受影響的依賴鏈 |
| AI 介入 | 藍色→紫色漸層,流動粒子動畫 | OpenClaw 正在分析的路徑 |
| 收合群組間 | 灰色虛線 | 群組之間的連線 |
### 3.4 互動行為
| 操作 | 行為 |
|------|------|
| 點擊群組 | 展開/收合群組,顯示內部服務 |
| 點擊服務節點 | 右側面板顯示該服務詳情 (指標/日誌/告警) |
| Hover 節點 | 顯示 tooltip (CPU/Memory/連線數) |
| 滾輪 | 縮放 |
| 拖曳空白 | 平移畫布 |
| 「全部展開」按鈕 | 展開所有群組 |
| 「全部收合」按鈕 | 收合到 Macro View |
| 「只看異常」按鈕 | 隱藏所有健康節點,只顯示 warning/critical |
---
## 第四章:細化實施步驟
### Phase 1: 基礎建設 (Day 1)
#### Task 1.1: 安裝依賴
```bash
cd apps/web
npm install @xyflow/react elkjs
```
**驗證**: `import { ReactFlow } from '@xyflow/react'` 能成功 import
**檔案影響**: `package.json`, `package-lock.json`
---
#### Task 1.2: 建立 topology 元件目錄結構
```
apps/web/src/components/topology/
├── index.ts # 匯出
├── ServiceTopology.tsx # 主元件
├── nodes/
│ ├── GroupNode.tsx # 群組節點 (可展開/收合)
│ ├── ServiceNode.tsx # 服務節點 (memo)
│ └── node-types.ts # nodeTypes 註冊
├── edges/
│ ├── TopologyEdge.tsx # 自定義邊線 (漸層+動畫)
│ └── edge-types.ts # edgeTypes 註冊
├── hooks/
│ ├── useTopologyData.ts # API → nodes/edges 轉換
│ └── useElkLayout.ts # elkjs 佈局引擎
├── utils/
│ ├── topology-colors.ts # 狀態→顏色映射 (從 tailwind.config.ts)
│ └── topology-icons.ts # 服務→Lucide icon 映射
└── topology.css # 邊線動畫 keyframes
```
**驗證**: 目錄結構正確建立
---
### Phase 2: 核心元件 (Day 2-3)
#### Task 2.1: ServiceNode.tsx — 服務節點
```typescript
// 關鍵設計決策:
// 1. 用 React.memo + 自定義 areEqual
// 2. Tailwind className 直接套用
// 3. Lucide icon 根據服務類型選擇
// 4. 狀態色彩從 topology-colors.ts
```
**檔案**: `apps/web/src/components/topology/nodes/ServiceNode.tsx`
**測試**: 渲染 1 個節點,確認 Tailwind 樣式 + Lucide icon 正確
**i18n**: 節點標籤用 `useTranslations('topology')`
---
#### Task 2.2: GroupNode.tsx — 群組節點
```typescript
// 關鍵設計決策:
// 1. 收合時: 顯示群組名稱 + 服務數 + 健康摘要
// 2. 展開時: 變成透明容器,內部由 elkjs 排列子節點
// 3. 邊框顏色: 藍(.110) / 紅(.188異常) / 紫(K3s) / 橘(外部)
// 4. 點擊標題列 toggle 展開/收合
```
**檔案**: `apps/web/src/components/topology/nodes/GroupNode.tsx`
**測試**: 收合→展開→收合 循環測試
---
#### Task 2.3: TopologyEdge.tsx — 自定義邊線
```typescript
// 關鍵設計決策:
// 1. 用 React Flow 的 BaseEdge + getSmoothStepPath
// 2. SVG linearGradient 漸層色
// 3. CSS stroke-dasharray 流動動畫 (零 JS 開銷)
// 4. AI 介入路徑: 藍紫漸層 + 粒子動畫 (SVG animateMotion)
```
**檔案**: `apps/web/src/components/topology/edges/TopologyEdge.tsx`
**檔案**: `apps/web/src/components/topology/topology.css`
**測試**: 三種邊線 (正常/異常/AI) 渲染正確
---
#### Task 2.4: useElkLayout.ts — elkjs 佈局引擎
```typescript
// 關鍵設計決策:
// 1. elkjs 異步執行 — 需要 loading 狀態
// 2. 群組嵌套: elk options { 'elk.algorithm': 'layered' }
// 3. 節點間距: nodeSpacing=20, layerSpacing=50
// 4. 邊線路由: 'elk.edgeRouting': 'ORTHOGONAL' (正交)
// 5. 方向: 'elk.direction': 'RIGHT' (左到右)
```
**檔案**: `apps/web/src/components/topology/hooks/useElkLayout.ts`
**測試**: 輸入 20 個節點,輸出合理的 x/y 座標
---
#### Task 2.5: useTopologyData.ts — API 資料轉換
```typescript
// 關鍵設計決策:
// 1. 從 /api/v1/dashboard 取得 hosts + services
// 2. 轉換為 React Flow 的 Node[] + Edge[] 格式
// 3. 加入 parentId 實現嵌套 (elkjs compound graph)
// 4. 節點狀態即時更新 (透過 Zustand store 或定時 polling)
```
**檔案**: `apps/web/src/components/topology/hooks/useTopologyData.ts`
**測試**: API 回傳 → 正確的 nodes/edges 結構
---
### Phase 3: 主元件組裝 (Day 3-4)
#### Task 3.1: ServiceTopology.tsx — 主元件
```typescript
// 組裝所有子元件:
// 1. ReactFlow + nodeTypes + edgeTypes
// 2. useTopologyData (API 資料)
// 3. useElkLayout (佈局計算)
// 4. 控制列 (全部展開/收合/只看異常)
// 5. MiniMap + Controls
// 6. 骨架屏 (elkjs 計算中顯示)
```
**檔案**: `apps/web/src/components/topology/ServiceTopology.tsx`
**測試**: 完整拓撲圖渲染 + 互動
---
#### Task 3.2: i18n 翻譯
```json
// messages/zh-TW.json
{
"topology": {
"title": "神經拓撲",
"expandAll": "全部展開",
"collapseAll": "全部收合",
"showAnomaliesOnly": "只看異常",
"healthy": "健康",
"warning": "警告",
"critical": "異常",
"aiDiagnosing": "AI 診斷中",
"services": "服務",
"pods": "Pods",
"allHealthy": "全部健康",
"infraGroup": "基礎設施",
"aiGroup": "AI/數據中心",
"k3sGroup": "K3s 叢集",
"externalGroup": "外部網路"
}
}
```
**檔案**: `messages/zh-TW.json`, `messages/en.json`
---
### Phase 4: 頁面整合 (Day 4-5)
#### Task 4.1: 首頁 `/` 整合
```
修改: apps/web/src/app/[locale]/page.tsx
新增: ServiceTopology 元件到中央區域
保留: 現有 Metrics Strip + Incident Feed + OpenClaw Panel
策略: 拓撲圖收合模式 (Macro View4-6 群組節點)
```
---
#### Task 4.2: 拓撲頁 `/topology` 升級
```
修改: apps/web/src/app/[locale]/topology/page.tsx
替換: 現有 host list → 完整 ServiceTopology (可展開)
新增: 篩選器 (按群組/狀態/服務類型)
```
---
#### Task 4.3: 神經指揮 `/neural-command` 整合
```
修改: apps/web/src/components/neural-command/NeuralLiveCenter.tsx
新增: 迷你版 ServiceTopology (SSH 指揮鏈視圖)
```
---
### Phase 5: 設計稿與視覺調校 (Day 5-6)
#### Task 5.1: HTML Mockup 製作 (3+ 版本)
差異化在佈局比例和視覺重心:
| 版本 | 差異 | 拓撲佔比 | 右面板 |
|------|------|---------|--------|
| VA | 拓撲主角 + 右側固定面板 | 65% | 待核准 + 統計 |
| VB | 拓撲+串流並排 + 右側 tab 切換 | 55% | tab: 核准/串流/統計 |
| VC | 拓撲全幅 + 底部折疊面板 | 80% | 底部抽屜式 |
**部署**: scp → 192.168.0.188 → http://192.168.0.188:8765/
---
#### Task 5.2: 統帥選擇後視覺調校
根據統帥回饋修改:
- 佈局比例
- 配色微調
- 互動細節
---
### Phase 6: 後端 API 支援 (Day 6-7)
#### Task 6.1: `/api/v1/dashboard` 擴充
```python
# 現有回傳: hosts (name, status, cpu, ram, services)
# 需擴充:
# 1. 每個 host 加入 group 分類 (infra/ai/k3s/external)
# 2. 服務間的依賴關係 (edges)
# 3. AI 介入狀態 (openclaw_diagnosing: [service_name])
```
**檔案**: `apps/api/src/api/v1/dashboard.py`
**檔案**: `apps/api/src/services/dashboard_service.py` (如果有)
---
#### Task 6.2: 服務依賴關係定義
```yaml
# 可能需要新增 ConfigMap 或靜態配置
# 定義哪些服務依賴哪些服務
dependencies:
awoooi-web → awoooi-api
awoooi-api → postgresql, redis, openclaw
awoooi-worker → postgresql, redis, ollama
openclaw → ollama, langfuse
...
```
**方案選擇**:
- A: 靜態配置 (YAML/JSON) — 簡單可控
- B: 從 OTEL Trace 自動推導 — 動態但複雜
- C: 從 K8s NetworkPolicy 推導 — 部分覆蓋
**建議**: 先 A (靜態配置),未來可加 B (OTEL 自動發現)
---
### Phase 7: 測試與驗收 (Day 7-8)
#### Task 7.1: TypeScript 驗證
```bash
cd apps/web && pnpm exec tsc --noEmit
```
#### Task 7.2: 生產建置
```bash
pnpm run build
```
#### Task 7.3: 視覺驗收
- 首頁拓撲圖收合模式
- 點擊展開每個群組
- AI 介入動畫
- 異常節點高亮
- 響應式 (收合 Sidebar 後拓撲圖自動調整)
#### Task 7.4: 效能驗收
- 40+ 節點全展開時 FPS ≥ 30
- elkjs 佈局計算 ≤ 500ms
- 單一節點狀態更新不觸發其他節點 re-render
---
## 第五章:風險與緩解
| 風險 | 等級 | 緩解 |
|------|------|------|
| elkjs API 學習成本 | 中 | 封裝在 useElkLayout.ts只暴露 layoutNodes() |
| elkjs 佈局計算阻塞 UI | 低 | Web Worker 或 setTimeout 分片 |
| 節點數 150+ DOM 效能 | 低 | 預設收合 (只 4-6 DOM),展開時 memo |
| 服務依賴定義維護 | 中 | 先靜態 YAML未來 OTEL 自動發現 |
| 設計與現有頁面衝突 | 低 | 拓撲圖是新增元件,不動現有佈局 |
---
## 第六章:時程預估
| Phase | 天數 | 內容 |
|-------|------|------|
| 1 | 1 | 安裝依賴 + 目錄結構 |
| 2 | 2 | 核心元件 (節點/邊線/佈局/資料) |
| 3 | 1 | 主元件組裝 + i18n |
| 4 | 1 | 頁面整合 (首頁/拓撲/神經指揮) |
| 5 | 2 | 設計稿 (3+版本) + 視覺調校 |
| 6 | 1 | 後端 API 擴充 |
| 7 | 1 | 測試 + 驗收 |
| **總計** | **~9 天** | |
---
## 第七章:需要統帥決策的事項
| # | 決策項 | 選項 | 建議 | 統帥決定 |
|---|--------|------|------|---------|
| 1 | 首頁拓撲圖佈局比例 | 65% / 55% / 80% | 待設計稿比較 | ⏳ |
| 2 | 右側面板模式 | 固定 / tab切換 / 底部抽屜 | 待設計稿比較 | ⏳ |
| 3 | 服務依賴定義方式 | 靜態YAML / OTEL自動 / 混合 | 先靜態 | ⏳ |
| 4 | 拓撲圖預設狀態 | 全部收合 / 展開異常群組 | 展開異常 | ⏳ |
| 5 | 是否先做 PoC 驗證 | 先 PoC 再做設計稿 / 並行 | 先 PoC | ⏳ |
---
## 第八章:需要的技術文檔 (輔助決策)
為了讓統帥能做出更完整的決策,以下文檔需要準備:
| # | 文檔 | 用途 | 狀態 |
|---|------|------|------|
| 1 | **React Flow + elkjs PoC Demo** | 在內網部署一個可互動的 PoC讓統帥親手操作展開/收合/篩選 | ⏳ 待製作 |
| 2 | **競品 UI 截圖集** | Datadog Service Map / Dynatrace Smartscape / Grafana Node Graph 的真實產品截圖 | ⏳ 待收集 |
| 3 | **3+ 版本 HTML 設計稿** | 高品質 mockup 部署到內網 192.168.0.188:8765 | ⏳ 待製作 |
| 4 | **現有 API 回傳格式文件** | `/api/v1/dashboard` 目前回傳什麼、需要擴充什麼 | ⏳ 待整理 |
| 5 | **服務依賴關係圖** | 67 個實體的完整依賴關係 (手動整理) | ⏳ 待整理 |
| 6 | **Bundle Size 影響報告** | 安裝 @xyflow/react + elkjs 後的 bundle 增量 | ⏳ 待測量 |
---
## 第九章:建議下一步
**統帥,我建議按以下順序推進:**
```
Step 1: 先做 PoC (React Flow + elkjs 嵌套群組)
→ 部署到內網讓統帥實際操作
→ 確認技術可行性和互動體驗
Step 2: 收集競品截圖 + 整理服務依賴關係
→ 給統帥參考市場做法
Step 3: 基於 PoC + 競品 → 製作 3+ 版本設計稿
→ 統帥選擇方向
Step 4: 確認方向後 → 正式實作 (Phase 1-7)
```
**統帥,這份計畫是否足夠完整?還需要補充哪些內容?**