问题
服务挂掉时,监控每 5 分钟检查一次,每次都发微信告警,造成告警轰炸。
方案
用 JSON 文件记录每个服务上次告警时间,30 分钟内同服务不重复发送;服务恢复后清掉记录,下次再挂立即重新告警。
核心逻辑
- 读取状态文件
.alert_state.json
- 失败的服务如果在 30 分钟内已告警过 → 跳过
- 否则发送告警并记录时间
- 每次检查后清理已恢复服务的记录
关键代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| yaml def send_wechat_alert(failed_results: List[dict], webhook_url: str): """ 发送企业微信机器人告警(Markdown 格式)
Args: failed_results: 失败的检查项列表 webhook_url: 企业微信机器人 Webhook 地址 """ if not failed_results or not webhook_url: return
if not HAS_REQUESTS: print("[WARN] 缺少 requests 库,无法发送告警") return
state = load_alert_state() now = datetime.now() to_send = [] need_save = False
for r in failed_results: name = r['name'] last_time_str = state.get(name)
if last_time_str: last_time = datetime.strptime(last_time_str, '%Y-%m-%d %H:%M:%S') minutes_diff = (now - last_time).total_seconds() / 60 if minutes_diff < 30: print(f" ⏭️ {name} 30分钟内已告警,跳过") continue
to_send.append(r) state[name] = now.strftime('%Y-%m-%d %H:%M:%S') need_save = True
if not to_send: print(" ℹ️ 所有失败项均在30分钟内,本次不重复告警") return
if need_save: save_alert_state(state)
lines = [ "## 🚨 服务健康检查告警", f"> 检查时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", f"> 失败项数: **{len(to_send)}**", "", ] for r in to_send: lines.append(f"- **{r['name']}** ({r['target']})") lines.append(f" > {r['error']}")
payload = { "msgtype": "markdown", "markdown": { "content": "\n".join(lines) } }
try: resp = requests.post(webhook_url, json=payload, timeout=5) if resp.status_code == 200: print(f"\n📤 企业微信告警已发送({len(to_send)} 项失败)") else: print(f"\n⚠️ 告警发送失败,HTTP {resp.status_code}: {resp.text}") except Exception as e: print(f"\n⚠️ 告警发送异常: {e}")
|
验证
连续 3 次故障只收到 1 条告警。