3v324v23's picture
Enhances platform with robust monitoring and notifications
4e22b4d
Raw
History Blame Contribute Delete
5.72 kB
import os
import httpx
from packages.core.logger import app_logger
# 告警 Webhook 配置(从环境变量读取)
FEISHU_WEBHOOK_URL = os.getenv("FEISHU_WEBHOOK_URL")
DINGTALK_WEBHOOK_URL = os.getenv("DINGTALK_WEBHOOK_URL")
WECOM_WEBHOOK_URL = os.getenv("WECOM_WEBHOOK_URL")
async def send_alert(title: str, message: str, level: str = "warning"):
"""
通用告警模块:接入钉钉/飞书/企业微信机器人的 Webhook。
支持同时发送到多个渠道。
Args:
title: 告警标题
message: 告警详情
level: 告警级别 (warning/error/critical)
"""
alert_msg = f"🚨 [ALERT - {level.upper()}] {title}: {message}"
# 记录日志
if level == "critical" or level == "error":
app_logger.error(alert_msg)
else:
app_logger.warning(alert_msg)
# 确定告警颜色和图标
if level == "critical":
color = "red"
emoji = "🔴"
elif level == "error":
color = "orange"
emoji = "🟠"
else:
color = "yellow"
emoji = "🟡"
# 发送到飞书
if FEISHU_WEBHOOK_URL:
await _send_to_feishu(title, message, level, emoji)
# 发送到钉钉
if DINGTALK_WEBHOOK_URL:
await _send_to_dingtalk(title, message, level, emoji)
# 发送到企业微信
if WECOM_WEBHOOK_URL:
await _send_to_wecom(title, message, level, emoji)
async def _send_to_feishu(title: str, message: str, level: str, emoji: str):
"""发送告警到飞书机器人"""
try:
payload = {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"content": f"{emoji} {title}",
"tag": "plain_text"
},
"template": "red" if level == "critical" else "orange" if level == "error" else "yellow"
},
"elements": [
{
"tag": "div",
"text": {
"content": f"**级别**: {level.upper()}\n\n**详情**:\n{message}",
"tag": "lark_md"
}
},
{
"tag": "hr"
},
{
"tag": "note",
"elements": [
{
"tag": "plain_text",
"content": f"海关数据系统告警 - {level.upper()}"
}
]
}
]
}
}
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(FEISHU_WEBHOOK_URL, json=payload)
if response.status_code == 200:
app_logger.info(f"Alert sent to Feishu successfully: {title}")
else:
app_logger.error(f"Failed to send alert to Feishu: {response.text}")
except Exception as e:
app_logger.error(f"Error sending alert to Feishu: {e}")
async def _send_to_dingtalk(title: str, message: str, level: str, emoji: str):
"""发送告警到钉钉机器人"""
try:
payload = {
"msgtype": "markdown",
"markdown": {
"title": f"{emoji} {title}",
"text": f"### {emoji} {title}\n\n"
f"**级别**: {level.upper()}\n\n"
f"**详情**:\n\n{message}\n\n"
f"---\n\n"
f"*海关数据系统告警*"
}
}
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(DINGTALK_WEBHOOK_URL, json=payload)
if response.status_code == 200:
app_logger.info(f"Alert sent to DingTalk successfully: {title}")
else:
app_logger.error(f"Failed to send alert to DingTalk: {response.text}")
except Exception as e:
app_logger.error(f"Error sending alert to DingTalk: {e}")
async def _send_to_wecom(title: str, message: str, level: str, emoji: str):
"""发送告警到企业微信机器人"""
try:
payload = {
"msgtype": "markdown",
"markdown": {
"content": f"## {emoji} {title}\n\n"
f"**级别**: <font color=\"warning\">{level.upper()}</font>\n\n"
f"**详情**:\n{message}\n\n"
f"> 海关数据系统告警"
}
}
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(WECOM_WEBHOOK_URL, json=payload)
if response.status_code == 200:
app_logger.info(f"Alert sent to WeCom successfully: {title}")
else:
app_logger.error(f"Failed to send alert to WeCom: {response.text}")
except Exception as e:
app_logger.error(f"Error sending alert to WeCom: {e}")
def send_alert_sync(title: str, message: str, level: str = "warning"):
"""
同步版本的告警发送(用于非异步上下文)
"""
import asyncio
try:
asyncio.create_task(send_alert(title, message, level))
except RuntimeError:
# 如果没有运行中的事件循环,只记录日志
alert_msg = f"🚨 [ALERT - {level.upper()}] {title}: {message}"
if level == "critical" or level == "error":
app_logger.error(alert_msg)
else:
app_logger.warning(alert_msg)