fix(telegram): 歷史按鈕改從 AnomalyCounter(Redis) 讀頻率,修復永遠顯示「無頻率統計資料」
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m45s
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 1m45s
根本原因: frequency_stats 從未持久化到 DB,get_by_id() 回傳永遠是 None 修復: 用 AnomalyCounter.derive_key_from_incident() 推導 anomaly_key, 直接從 Redis 查即時頻率與處置分佈統計 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2655,9 +2655,10 @@ class TelegramGateway:
|
||||
"""
|
||||
ADR-050 P2: 傳送事件頻率統計訊息
|
||||
|
||||
2026-04-01 Claude Code (ADR-050 P2): history button handler
|
||||
2026-04-10 ogt: 修復 — frequency_stats 不存 DB,改從 AnomalyCounter (Redis) 即時查詢
|
||||
"""
|
||||
from src.repositories.incident_repository import get_incident_repository
|
||||
from src.services.anomaly_counter import get_anomaly_counter, AnomalyCounter
|
||||
|
||||
try:
|
||||
repo = get_incident_repository()
|
||||
@@ -2667,47 +2668,60 @@ class TelegramGateway:
|
||||
await self.send_notification(f"⚠️ 找不到事件 <code>{html.escape(incident_id)}</code>")
|
||||
return
|
||||
|
||||
fs = incident.frequency_stats
|
||||
if not fs:
|
||||
# frequency_stats 不持久化,從 AnomalyCounter (Redis) 即時查詢
|
||||
anomaly_key = AnomalyCounter.derive_key_from_incident(incident)
|
||||
if not anomaly_key:
|
||||
await self.send_notification(
|
||||
f"📊 <b>事件歷史</b>\n\n🔖 <code>{html.escape(incident.incident_id)}</code>\n\n無頻率統計資料"
|
||||
f"📊 <b>事件歷史</b>\n\n🔖 <code>{html.escape(incident_id)}</code>\n\n⚠️ 無法推導告警鍵(signals 為空)"
|
||||
)
|
||||
return
|
||||
|
||||
counter = get_anomaly_counter()
|
||||
freq = await counter.record_anomaly({
|
||||
"alert_name": incident.signals[0].alert_name if incident.signals else "",
|
||||
"service": incident.affected_services[0] if incident.affected_services else "",
|
||||
"namespace": (incident.signals[0].labels or {}).get("namespace", "") if incident.signals else "",
|
||||
"error_type": (incident.signals[0].labels or {}).get("reason", (incident.signals[0].labels or {}).get("error_type", "")) if incident.signals else "",
|
||||
})
|
||||
disposition = await counter.get_disposition_stats(anomaly_key)
|
||||
|
||||
lines = [
|
||||
f"📊 <b>事件歷史統計</b>",
|
||||
f"",
|
||||
f"🔖 <code>{html.escape(incident.incident_id)}</code>",
|
||||
f"🔑 告警鍵: <code>{html.escape(fs.anomaly_key[:60])}</code>",
|
||||
f"🔖 <code>{html.escape(incident_id)}</code>",
|
||||
f"🔑 告警鍵: <code>{html.escape(anomaly_key)}</code>",
|
||||
f"",
|
||||
f"⏱ <b>發生頻率</b>",
|
||||
f" 1小時: {fs.count_1h} 次",
|
||||
f" 24小時: {fs.count_24h} 次",
|
||||
f" 7天: {fs.count_7d} 次",
|
||||
f" 30天: {fs.count_30d} 次",
|
||||
f" 1小時: {freq.count_1h} 次",
|
||||
f" 24小時: {freq.count_24h} 次",
|
||||
f" 7天: {freq.count_7d} 次",
|
||||
f" 30天: {freq.count_30d} 次",
|
||||
]
|
||||
|
||||
if fs.auto_repair_count > 0:
|
||||
if freq.auto_repair_count > 0:
|
||||
lines += [
|
||||
f"",
|
||||
f"🔧 <b>自動修復</b>",
|
||||
f" 執行次數: {fs.auto_repair_count}",
|
||||
f" 執行次數: {freq.auto_repair_count}",
|
||||
]
|
||||
if fs.last_repair_action:
|
||||
lines.append(f" 最後動作: {html.escape(fs.last_repair_action[:80])}")
|
||||
if freq.last_repair_action:
|
||||
lines.append(f" 最後動作: {html.escape(freq.last_repair_action)}")
|
||||
|
||||
# 2026-04-07 Claude Code: Sprint 4 D2 — 處置分佈明細
|
||||
total_res = fs.total_resolution_count
|
||||
# 處置分佈
|
||||
auto_r = disposition.get("auto_repair_count", 0)
|
||||
cold_s = disposition.get("cold_start_trust_count", 0)
|
||||
human_a = disposition.get("human_approved_count", 0)
|
||||
manual_r = disposition.get("manual_resolved_count", 0)
|
||||
total_res = auto_r + cold_s + human_a + manual_r
|
||||
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
|
||||
auto_rate = int((auto_r + cold_s) / total_res * 100)
|
||||
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" 🤖 自動修復: {auto_r}",
|
||||
f" ❄️ 冷啟動信任: {cold_s}",
|
||||
f" 👤 人工審核: {human_a}",
|
||||
f" 🔧 手動處理: {manual_r}",
|
||||
f" 📈 自動化率: <b>{auto_rate}%</b>",
|
||||
]
|
||||
|
||||
@@ -2715,7 +2729,7 @@ class TelegramGateway:
|
||||
|
||||
except Exception as e:
|
||||
logger.warning("send_incident_history_failed", incident_id=incident_id, error=str(e))
|
||||
await self.send_notification(f"⚠️ 無法取得歷史統計: {html.escape(str(e)[:100])}")
|
||||
await self.send_notification(f"⚠️ 無法取得歷史統計: {html.escape(str(e))}")
|
||||
|
||||
async def _send_reanalyze_result(self, incident_id: str) -> None:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user