diff --git a/apps/api/src/services/decision_manager.py b/apps/api/src/services/decision_manager.py index 3bfc2b64..daf6f84e 100644 --- a/apps/api/src/services/decision_manager.py +++ b/apps/api/src/services/decision_manager.py @@ -41,6 +41,41 @@ logger = structlog.get_logger(__name__) PLAYBOOK_SIMILARITY_THRESHOLD = 0.85 # 相似度 >= 85% 直接使用 Playbook +# ============================================================================= +# Phase 31 (ADR-067 2026-04-10): Log 異常摘要 — NemoTron deepseek-r1:14b +# ============================================================================= + +async def _send_log_summary(incident: "Incident") -> None: + """ + 非同步取得 Pod log 異常摘要,用 NemoTron bot 發到 SRE 群組 + 觸發點:_push_decision_to_telegram 發完審批卡後 + """ + try: + target = incident.affected_services[0] if incident.affected_services else None + if not target: + return + namespace = "awoooi-prod" + if incident.signals: + namespace = incident.signals[0].labels.get("namespace", "awoooi-prod") + + from src.services.log_summary_service import get_log_summary_service + svc = get_log_summary_service() + summary = await svc.summarize_with_soft_timeout(pod_name=target, namespace=namespace) + if not summary: + return + + from src.services.telegram_gateway import get_telegram_gateway + tg = get_telegram_gateway() + await tg.send_as_nemotron( + f"📋 Log 異常摘要{target}\n{summary}" + ) + import structlog as _sl + _sl.get_logger(__name__).info("log_summary_sent", target=target, incident_id=incident.incident_id) + except Exception as e: + import structlog as _sl + _sl.get_logger(__name__).warning("log_summary_failed", error=str(e)) + + # ============================================================================= # Telegram 推送 (Phase 6.5: 決策就緒通知) # ============================================================================= @@ -200,6 +235,10 @@ async def _push_decision_to_telegram( except Exception as _e: logger.warning("telegram_message_id_db_save_failed", incident_id=incident.incident_id, error=str(_e)) + # Phase 31 (ADR-067 2026-04-10): Log 異常摘要 — NemoTron deepseek-r1:14b + # 非同步執行,不阻塞主流程 + asyncio.create_task(_send_log_summary(incident)) + # 🔴 發送成功後設置去重 key (TTL 10 分鐘) await redis.setex(dedup_key, 600, "1")