feat(api+telegram): Sprint 4 Phase C+D — API 端點 + Telegram 處置統計

Phase C: API 端點
- C1: GET /api/v1/stats/disposition — 完整處置分佈統計
  - DispositionSummary: auto/human/manual/cold_start + auto_rate
  - DispositionByAnomaly: 按異常類型明細 (最多 20 筆)
  - Redis SCAN + HGETALL 聚合
- C2: GET /api/v1/auto-repair/stats 擴充 disposition_summary

Phase D: Telegram 告警格式
- D1: 告警卡片加處置統計行
  - 🤖 自動: N | 👤 審核: N | 🔧 手動: N
  - 自動化率百分比
- D2: 歷史按鈕強化處置分佈明細
  - 完整 5 項計數 + 自動化率

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-07 12:17:20 +08:00
parent 9253281d46
commit a85e9ced08
3 changed files with 183 additions and 3 deletions

View File

@@ -240,12 +240,32 @@ class TelegramMessage:
"PERMANENT_FIX": "🚨",
}.get(freq.get("escalation_level"), "")
# 2026-04-07 Claude Code: Sprint 4 D1 — 處置統計行
auto_r = freq.get("auto_repair_count", 0)
human_a = freq.get("human_approved_count", 0)
manual_r = freq.get("manual_resolved_count", 0)
cold_s = freq.get("cold_start_trust_count", 0)
total_res = freq.get("total_resolution_count", 0)
# 處置分佈行 (只在有處置紀錄時顯示)
disposition_line = ""
if total_res > 0:
auto_total = auto_r + cold_s
auto_rate = int(auto_total / total_res * 100) if total_res > 0 else 0
disposition_line = (
f"├ 🤖 自動: <code>{auto_total}</code>"
f" | 👤 審核: <code>{human_a}</code>"
f" | 🔧 手動: <code>{manual_r}</code>\n"
f"├ 自動化率: <b>{auto_rate}%</b>\n"
)
frequency_block = (
f"━━━━━━━━━━━━━━━━━━━\n"
f"📊 <b>頻率統計</b> {escalation_emoji}\n"
f"├ 1h: <code>{freq.get('count_1h', 0)}</code> 次\n"
f" 24h: <code>{freq.get('count_24h', 0)}</code> 次\n"
f"└ 修復: <code>{freq.get('auto_repair_count', 0)}</code> 次\n"
f"├ 1h: <code>{freq.get('count_1h', 0)}</code> 次"
f" | 24h: <code>{freq.get('count_24h', 0)}</code> 次\n"
f"{disposition_line}"
f"└ 累計修復: <code>{auto_r}</code> 次\n"
)
if freq.get("escalation_level"):
frequency_block += f"🔺 升級: <b>{freq['escalation_level']}</b>\n"
@@ -2550,6 +2570,21 @@ class TelegramGateway:
if fs.last_repair_action:
lines.append(f" 最後動作: {html.escape(fs.last_repair_action[:80])}")
# 2026-04-07 Claude Code: Sprint 4 D2 — 處置分佈明細
total_res = fs.total_resolution_count
if total_res > 0:
auto_total = fs.auto_repair_count + fs.cold_start_trust_count
auto_rate = int(auto_total / total_res * 100) if total_res > 0 else 0
lines += [
f"",
f"📋 <b>處置分佈</b> (共 {total_res} 次)",
f" 🤖 自動修復: {fs.auto_repair_count}",
f" ❄️ 冷啟動信任: {fs.cold_start_trust_count}",
f" 👤 人工審核: {fs.human_approved_count}",
f" 🔧 手動處理: {fs.manual_resolved_count}",
f" 📈 自動化率: <b>{auto_rate}%</b>",
]
await self.send_notification("\n".join(lines))
except Exception as e: