refactor(telegram): migrate alert_routes sender to EventRouter (ADR-019 Phase 5)

routes/alert_routes.py 的 send_telegram_message() 是 Alertmanager webhook 通用告警
出口,原本直接 POST sendMessage 並對每個 chat_id 迴圈。改走 services.event_router.
dispatch_sync() 統一入口(event_type=alertmanager_webhook, severity=alert)。

行為變化:
- 移除手動 chat_id 迴圈,改傳 admin_chat_ids 給 EventRouter(內部仍逐一發)
- 新增 ADR-012 三層分流(L0/L1/L2)+ JSONL queue replay 失敗重送
- parse_mode 參數保留簽名向後相容,但實際統一走 EventRouter HTML 模板
- caller(Alertmanager webhook handler)的 try/except 結構未動

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
OoO
2026-05-02 13:08:00 +08:00
parent edfe38e87d
commit ea78d0814b

View File

@@ -96,31 +96,37 @@ def check_alert_auth(f):
def send_telegram_message(message: str, parse_mode: str = 'HTML') -> bool:
"""發送 Telegram 訊息"""
"""
發送 Telegram 訊息
ADR-019 Phase 5: 改走 EventRouter 統一入口,享 retry + JSONL queue replay。
parse_mode 參數保留向後相容EventRouter 內部統一 HTML舊 caller 若指定
其他 mode 會被忽略;此 route 原本就只用 HTML影響面=0
"""
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_IDS:
logger.warning("[Alert] Telegram 未設定,無法發送告警")
return False
success = True
for chat_id in TELEGRAM_CHAT_IDS:
try:
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {
'chat_id': chat_id,
'text': message,
'parse_mode': parse_mode
}
response = requests.post(url, json=payload, timeout=10)
if response.status_code != 200:
logger.error(f"[Alert] Telegram 發送失敗: {response.text}")
success = False
else:
logger.info(f"[Alert] Telegram 訊息已發送到 {chat_id}")
except Exception as e:
logger.error(f"[Alert] Telegram 發送錯誤: {e}")
success = False
return success
try:
from services.event_router import dispatch_sync
result = dispatch_sync(event={
"event_type": "alertmanager_webhook",
"severity": "alert",
"source": "Alertmanager.Webhook",
"title": "Alertmanager 告警",
"summary": message[:400],
"status": "received",
"payload": {"raw_message": message, "parse_mode": parse_mode},
}, admin_chat_ids=TELEGRAM_CHAT_IDS)
delivered = bool(result.get("delivered"))
if not delivered:
logger.error(f"[Alert] EventRouter 告警未送達: {result.get('errors')}")
else:
logger.info(f"[Alert] EventRouter 告警已派送 sent={result.get('sent')}")
return delivered
except Exception as e:
logger.error(f"[Alert] EventRouter dispatch 失敗: {e}")
return False
def format_alert_message(alert: dict, status: str) -> str: