智能告警降噪:先合并事件,再通知人
智能告警降噪先合并事件再通知人一、告警噪声的本质是同一件事件被重复通知很多团队的告警系统在出现一个故障时会同时触发几十条告警数据库慢查询、应用延迟升高、HTTP 500 错误增多、消息队列堆积、用户体验下降……这些告警其实都是同一件事件的不同表现但告警系统不知道它们是相关的所以会逐条通知值班人员。告警降噪的第一原则能合并的告警必须合并人只应该收到事件而不是信号。我们在生产中要求同一个服务在 10 分钟内的所有告警必须合并成一条通知附带完整的上下文影响了什么、可能的原因、建议的处理步骤。二、告警合并的策略时间窗口 拓扑关系flowchart TD A[原始告警信号] -- B[时间窗口合并] B -- C{同一服务?} C --|是| D[合并到同一个事件] C --|否| E[检查拓扑关系] E -- F{上下游依赖?} F --|是| G[只通知下游根因告警] F --|否| H[分别创建事件] D -- I[事件通知] G -- I H -- I I -- J[值班人员收到合并后的通知] style A fill:#f9f,stroke:#333 style D fill:#bfb,stroke:#333 style G fill:#bbf,stroke:#333 style J fill:#fbb,stroke:#333告警合并的核心是两个维度时间窗口和拓扑关系。时间窗口合并同一服务在指定时间窗口比如 10 分钟内的所有告警合并成一个事件。# 告警合并器简化版 from datetime import datetime, timedelta from typing import List, Dict from dataclasses import dataclass, field dataclass class Alert: alert_id: str service: str alertname: str severity: str started_at: datetime tags: Dict[str, str] description: str dataclass class Incident: incident_id: str service: str severity: str started_at: datetime alerts: List[Alert] field(default_factorylist) status: str open # open / acknowledged / resolved def add_alert(self, alert: Alert): self.alerts.append(alert) # 更新严重等级取最高的 severity_order {critical: 0, warning: 1, info: 2} if severity_order[alert.severity] severity_order[self.severity]: self.severity alert.severity def summary(self) - str: 生成事件的摘要 alert_names [a.alertname for a in self.alerts] return f服务 {self.service} 在 {self.started_at} 发生异常: {, .join(set(alert_names))} class AlertMerger: def __init__(self, time_window_minutes: int 10): self.time_window timedelta(minutestime_window_minutes) self.open_incidents: Dict[str, Incident] {} # service - Incident def process_alert(self, alert: Alert) - Incident: 处理一条告警返回它属于哪个事件 # 检查是否能合并到已有的事件 if alert.service in self.open_incidents: incident self.open_incidents[alert.service] # 检查时间窗口 if datetime.now() - incident.started_at self.time_window: incident.add_alert(alert) return incident # 不能合并创建新事件 incident Incident( incident_idfinc-{datetime.now().strftime(%Y%m%d%H%M%S)}, servicealert.service, severityalert.severity, started_atalert.started_at ) incident.add_alert(alert) self.open_incidents[alert.service] incident return incident拓扑关系合并如果服务 A 的告警是因为服务 B下游故障导致的那应该只通知服务 B 的告警。这需要一个服务依赖拓扑。我们在每个服务的配置里标注了它的下游依赖告警系统会根据拓扑自动抑制上游服务的告警。# 服务拓扑配置示例 service: order-service dependencies: - service: user-service type: grpc critical: true - service: payment-service type: http critical: true - service: redis-cache type: redis critical: false当payment-service故障时告警系统会检查所有依赖它的服务比如order-service然后只发送payment-service的告警抑制order-service的告警因为后者的告警是次生告警。三、智能降噪用 AI 识别告警模式时间窗口合并和拓扑合并是确定性规则能解决 80% 的告警噪声。但还有些噪声是不确定性的比如网络抖动导致的偶发超时可能 10 分钟后自动恢复开发在调试时触发的测试告警下游服务的计划内维护这些场景用规则很难覆盖但AI 可以识别模式。我们的做法是把所有告警记录包括误报喂给一个分类模型让它学习什么样的告警模式通常是误报。# 告警模式识别模型简化版 from sklearn.ensemble import RandomForestClassifier import pandas as pd # 特征工程把告警转换成模型能理解的特征 def extract_alert_features(alerts: List[Alert]) - pd.DataFrame: 提取告警的特征 features [] for alert in alerts: feature { service: alert.service, alertname: alert.alertname, severity: alert.severity, hour_of_day: alert.started_at.hour, day_of_week: alert.started_at.weekday(), duration_minutes: (alert.ended_at - alert.started_at).total_seconds() / 60, similar_alerts_count: count_similar_alerts(alert), is_deployment_related: check_deployment(alert), is_downstream_alert: check_downstream(alert), } features.append(feature) return pd.DataFrame(features) # 训练模型用历史告警数据标注哪些是误报 model RandomForestClassifier(n_estimators100) train_data load_historical_alerts() X extract_alert_features(train_data[alerts]) y train_data[is_false_positive] model.fit(X, y) # 预测新告警是否是误报 def predict_false_positive(alert: Alert) - float: 预测告警是误报的概率 features extract_alert_features([alert]) probability model.predict_proba(features)[0][1] # 返回是正样本的概率 return probability落地时的关键AI 模型的预测结果不要直接用来屏蔽告警而是用来调整告警的优先级。比如模型预测某条告警有 80% 概率是误报那就把它从 P1 降级到 P3而不是完全不通知。四、降噪效果的量化评估告警降噪做得好不好不能只凭感觉要量化评估。我们关注三个指标1. 告警压缩比合并前告警数 / 合并后事件数目标≥ 5:1计算方法比如原来每天 100 条告警合并后变成 20 个事件压缩比就是 5:12. 误报率被人工标记为误报的事件数 / 总事件数目标≤ 10%优化方法分析误报的共同特征补充到合并规则或 AI 模型中3. 平均确认时间MTTA从事件创建到被人工确认的时间目标P0 2min, P1 10min优化方法改进事件通知的内容质量让值班人员能快速判断严重性# 降噪效果评估报告每周自动生成 def generate_noise_reduction_report(start: datetime, end: datetime) - dict: 生成告警降噪效果报告 alerts get_alerts_in_timerange(start, end) incidents get_incidents_in_timerange(start, end) compression_ratio len(alerts) / len(incidents) if incidents else 0 false_positive_rate count_false_positives(incidents) / len(incidents) mtta calculate_mtta(incidents) report { period: f{start.date()} ~ {end.date()}, total_alerts: len(alerts), total_incidents: len(incidents), compression_ratio: f{compression_ratio:.1f}:1, false_positive_rate: f{false_positive_rate:.1%}, mtta_p0: f{mtta[P0]:.1f}min, mtta_p1: f{mtta[P1]:.1f}min, recommendations: generate_recommendations(compression_ratio, false_positive_rate, mtta) } return report五、总结智能告警降噪的核心不是少发告警而是发对的告警合并重复的告警抑制次生的告警。时间窗口合并和拓扑合并能解决 80% 的问题AI 模式识别能进一步优化。落地时的关键三点同一时间窗口内的告警要合并、上下游依赖的告警要抑制、降噪效果要量化评估。做到这三点告警系统才是帮手做不到就只是换了个方式轰炸值班人员。