feat(telegram): enforce canonical product routing
This commit is contained in:
@@ -569,38 +569,114 @@ class ReportGenerationService:
|
||||
Graceful Degradation: 失敗只記錄 log,不拋出例外
|
||||
"""
|
||||
try:
|
||||
from src.services.telegram_gateway import (
|
||||
_telegram_send_delivery_succeeded,
|
||||
get_telegram_gateway,
|
||||
)
|
||||
|
||||
gateway = get_telegram_gateway()
|
||||
if not gateway.canonical_destination_chat_id(
|
||||
product_id="awoooi",
|
||||
signal_family="product_raw_monitoring",
|
||||
severity="P3",
|
||||
):
|
||||
logger.warning(
|
||||
"daily_report_no_send",
|
||||
reason="canonical_route_unavailable",
|
||||
)
|
||||
return
|
||||
|
||||
kpi = await self.collect_daily_kpi()
|
||||
source_health = await self.collect_report_source_health(days=1)
|
||||
report_text = self.format_daily_report(kpi, source_health)
|
||||
|
||||
from src.services.telegram_gateway import get_telegram_gateway
|
||||
gateway = get_telegram_gateway()
|
||||
await gateway.send_to_group(report_text, parse_mode="HTML")
|
||||
|
||||
logger.info(
|
||||
"daily_report_sent",
|
||||
total_alerts=kpi.total_alerts,
|
||||
auto_repair_rate=f"{kpi.auto_repair_rate:.1%}",
|
||||
result = await gateway.send_to_group(
|
||||
report_text,
|
||||
parse_mode="HTML",
|
||||
product_id="awoooi",
|
||||
signal_family="product_raw_monitoring",
|
||||
severity="P3",
|
||||
)
|
||||
|
||||
if _telegram_send_delivery_succeeded(result):
|
||||
logger.info(
|
||||
"daily_report_sent",
|
||||
total_alerts=kpi.total_alerts,
|
||||
delivery_status=result.get("_awooop_delivery_status", "sent"),
|
||||
auto_repair_rate=f"{kpi.auto_repair_rate:.1%}",
|
||||
)
|
||||
else:
|
||||
logger.warning(
|
||||
"daily_report_no_send",
|
||||
total_alerts=kpi.total_alerts,
|
||||
delivery_status=(
|
||||
result.get(
|
||||
"_awooop_delivery_status",
|
||||
"missing_provider_ack",
|
||||
)
|
||||
if isinstance(result, dict)
|
||||
else "missing_provider_ack"
|
||||
),
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error("daily_report_failed", error=str(e))
|
||||
|
||||
async def send_monthly_report(self) -> bool:
|
||||
"""收集月報資料 → 組裝 → 推送 Telegram SRE 群組。"""
|
||||
try:
|
||||
from src.services.telegram_gateway import (
|
||||
_telegram_send_delivery_succeeded,
|
||||
get_telegram_gateway,
|
||||
)
|
||||
|
||||
gateway = get_telegram_gateway()
|
||||
if not gateway.canonical_destination_chat_id(
|
||||
product_id="awoooi",
|
||||
signal_family="product_raw_monitoring",
|
||||
severity="P3",
|
||||
):
|
||||
logger.warning(
|
||||
"monthly_report_no_send",
|
||||
reason="canonical_route_unavailable",
|
||||
)
|
||||
return False
|
||||
|
||||
source_health = await self.collect_report_source_health(days=30)
|
||||
report_text = self.format_monthly_report(source_health)
|
||||
|
||||
from src.services.telegram_gateway import get_telegram_gateway
|
||||
gateway = get_telegram_gateway()
|
||||
await gateway.send_to_group(report_text, parse_mode="HTML")
|
||||
|
||||
logger.info(
|
||||
"monthly_report_sent",
|
||||
source_ok=(source_health.get("rollups") or {}).get("source_ok_count"),
|
||||
source_total=(source_health.get("rollups") or {}).get("source_count"),
|
||||
result = await gateway.send_to_group(
|
||||
report_text,
|
||||
parse_mode="HTML",
|
||||
product_id="awoooi",
|
||||
signal_family="product_raw_monitoring",
|
||||
severity="P3",
|
||||
)
|
||||
return True
|
||||
|
||||
if _telegram_send_delivery_succeeded(result):
|
||||
logger.info(
|
||||
"monthly_report_sent",
|
||||
source_ok=(source_health.get("rollups") or {}).get(
|
||||
"source_ok_count"
|
||||
),
|
||||
delivery_status=result.get("_awooop_delivery_status", "sent"),
|
||||
source_total=(source_health.get("rollups") or {}).get(
|
||||
"source_count"
|
||||
),
|
||||
)
|
||||
return True
|
||||
|
||||
logger.warning(
|
||||
"monthly_report_no_send",
|
||||
delivery_status=(
|
||||
result.get(
|
||||
"_awooop_delivery_status",
|
||||
"missing_provider_ack",
|
||||
)
|
||||
if isinstance(result, dict)
|
||||
else "missing_provider_ack"
|
||||
),
|
||||
)
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error("monthly_report_failed", error=str(e))
|
||||
return False
|
||||
@@ -663,7 +739,10 @@ class ReportGenerationService:
|
||||
import asyncio as _asyncio
|
||||
report_text = self.format_postmortem(data)
|
||||
await self._persist_postmortem_km(data, report_text)
|
||||
from src.services.telegram_gateway import get_telegram_gateway
|
||||
from src.services.telegram_gateway import (
|
||||
_telegram_send_delivery_succeeded,
|
||||
get_telegram_gateway,
|
||||
)
|
||||
gateway = get_telegram_gateway()
|
||||
|
||||
max_attempts = 3
|
||||
@@ -671,7 +750,22 @@ class ReportGenerationService:
|
||||
last_error: Exception | None = None
|
||||
for attempt in range(1, max_attempts + 1):
|
||||
try:
|
||||
await gateway.send_to_group(report_text, parse_mode="HTML")
|
||||
result = await gateway.send_to_group(
|
||||
report_text,
|
||||
parse_mode="HTML",
|
||||
product_id="awoooi",
|
||||
signal_family="incident_lifecycle",
|
||||
severity="P1",
|
||||
)
|
||||
if not _telegram_send_delivery_succeeded(result):
|
||||
delivery_status = (
|
||||
result.get("_awooop_delivery_status")
|
||||
if isinstance(result, dict)
|
||||
else None
|
||||
)
|
||||
raise RuntimeError(
|
||||
str(delivery_status or "missing_provider_ack")
|
||||
)
|
||||
logger.info(
|
||||
"postmortem_sent",
|
||||
incident_id=incident_id,
|
||||
@@ -705,7 +799,23 @@ class ReportGenerationService:
|
||||
f"Duration: {duration_minutes:.1f} 分鐘\n"
|
||||
f"Error: {str(last_error)[:200]}"
|
||||
)
|
||||
await gateway.send_to_group(fallback_text, parse_mode="HTML")
|
||||
fallback_result = await gateway.send_to_group(
|
||||
fallback_text,
|
||||
parse_mode="HTML",
|
||||
product_id="awoooi",
|
||||
signal_family="incident_lifecycle",
|
||||
severity="P1",
|
||||
)
|
||||
if not _telegram_send_delivery_succeeded(fallback_result):
|
||||
logger.error(
|
||||
"postmortem_fallback_no_send",
|
||||
incident_id=incident_id,
|
||||
delivery_status=(
|
||||
fallback_result.get("_awooop_delivery_status")
|
||||
if isinstance(fallback_result, dict)
|
||||
else "missing_provider_ack"
|
||||
),
|
||||
)
|
||||
except Exception as _fe:
|
||||
logger.error(
|
||||
"postmortem_fallback_failed",
|
||||
|
||||
Reference in New Issue
Block a user