ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

监控告警详细设计:从通知到现场还原,打造可用的告警详情模块

监控告警详细设计:从通知到现场还原,打造可用的告警详情模块 开头做监控告警系统最怕的一件事不是告警不够多而是告警来了你盯着屏幕干瞪眼。我们XNMS项目里的监控告警模块早期就是这样告警倒是能发出来值班群里的消息一条接一条Prometheus也好、自研采集也好确实把“系统异常”这件事通知到了人。但人收到通知之后呢打开详情页里面就孤零零几个字段告警级别、资源IP、当前值、触发时间。然后呢没了。CPU到了95%是哪台机器跑的是什么业务过去半小时曲线是什么样子有没有对应日志以前有没有发生过负责这个系统的人是谁全部要另外开终端去查。那段时间我们内部开玩笑说告警系统是个负责喊救命的门卫喊完之后人就走了连伤者躺哪、什么伤情都不管。后来我们痛下决心把“告警详细信息”这一块单独拎出来做了一次彻底的升级。整个过程踩了不少坑也沉淀了一些可复用的方案。今天就把我们XNMS项目里监控告警详细信息模块的设计思路、数据建模、实现链路、以及实际排障记录完整整理出来给同样在自建告警平台的朋友一个参考。1. XNMS监控告警的痛点告警有通知没有现场1.1 一个真实的告警处理场景先还原一个我们项目里的真实场景。某个深夜值班手机弹出告警——某支付网关节点的响应时间超过5秒持续3分钟。如果只看这一行你根本没法判断到底该不该起床处理。是流量突增是数据库慢查询拖垮了接口是下游服务超时导致线程池耗尽还是机器负载不够了你当然可以爬起来先SSH到跳板机再找到那台节点敲几行命令看负载再翻日志再查监控面板折腾二十分钟才敢判断“好像是数据库那边的问题”。等顺着链路查到数据库的时候可能已经攒了好几个告警了。XNMS项目里监控告警模块的价值就是在告警通知发出之后把“查找现场”这个过程从二十分钟压缩到十秒。而核心手段就是——把告警的详细信息做厚。信息越全定位越快值班的人就越从容。1.2 “详细信息”到底是什么很多人一听“告警详细信息”下意识以为就是给告警加几个字段。比如加上“所属业务”、“负责人”、“服务器IP”就完事了。这个理解太浅了。真正可用的告警详细信息是一整套“故障现场还原”的能力。它至少包含五个维度告警本身的基础信息告警ID、规则名、触发值、阈值、持续时间、告警级别。资源对象的静态信息主机IP、所属业务系统、责任人、所在机柜/可用区、操作系统版本、部署的容器和中间件。故障发生前后的动态上下文指标在触发前后30分钟的趋势曲线采集到的日志片段进程和端口的存活状态。关联信息这个告警在主机的维度上历史出现过几次最近一次是什么时候当时是怎么恢复的有没有关联的变更单处置辅助信息应该找谁确认有哪些应急预案链接是否已经有人认领正在处理。这五个维度组合起来才叫“详细信息”。单独拿出来任何一块都只是数据不解决问题。我们这次升级本质上就是把这五块信息全部串起来在告警详情页里一次性呈现出来。1.3 三种角色的诉求差异在动手设计之前我们先把使用告警信息系统的角色过了一遍不同角色对“详细信息”的诉求差别非常大角色核心诉求详情页里最关注的内容一线值班人员快速判断是否紧急、是否需要升级影响范围、业务归属、持续时长、当前趋势二线运维/研发快速定位根因指标曲线、日志片段、历史记录、变更关联运维负责人评估告警质量和团队响应效率告警是否误报、响应时长、认领人、处理结论这意味着详情页不能做成千篇一律的通用模板必须在同一个页面里做信息分层。当然这是我们后来迭代了半年的经验一开始我们也是“所有人在同一张表里找字段”结果谁都嫌不好用。2. 告警详细信息的数据设计与信息建模2.1 信息从哪来五个数据源的汇聚要把详情做厚首先得盘清楚数据源。XNMS项目里我们最终接入了五类数据源指标数据源主要是Prometheus和自研Agent采集的系统指标、业务指标存到时序库里我们用的是VictoriaMetrics。日志数据源应用日志统一走Filebeat采集入Kafka后写ESXNMS通过接口按关键字和主机维度做检索。资产配置库这是我们自己维护的一个CMDB记录每台机器的归属、业务、负责人、配置项。变更系统发布平台和执行工单的记录能够查询某个服务或者主机在某个时间点的变更动作。告警历史库XNMS自身存储的历史告警和恢复记录。在那个版本里我们没有把CMDB、变更系统的数据直接同步过来做冗余存储而是采用“查询时实时聚合”的方式。因为资产和变更信息更新频繁冗余存储搞不好就是旧数据反而误导人。2.2 字段体系的划分我们最终确定了告警详情数据结构主要分四大块第一块是告警事件自身。这条告警是谁触发的、规则怎么定义、值是多少、持续了多久、目前状态是什么。这些字段在告警产生那一刻就固定下来不随外部系统变化。第二块是资源上下文。告警对象是一台VM还是一套K8s DeploymentIP是什么业务归属是什么责任人是谁这里我们特意把“静态属性”和“动态属性”分开存储。比如机器名、可用区属于静态当前Pod副本数、进程存活状态属于动态。动态信息理论上应该在告警触发时抓取一次快照因为等你去查的时候可能已经恢复了。第三块是故障现场信息。最核心的就是指标趋势和日志片段其次是端口连通性、系统负载等实时探测结果。这类信息过了黄金时间之后价值会锐减所以必须在告警触发时同步采集。第四块是关联关系信息。历史告警列表、相似告警、关联变更记录、处理评论、预案链接。这个四块模型后来也成了我们详情页的四大区域前端拿来即用不用再做二次理解。2.3 动静分离详情快照机制说到快照这是我们踩坑最深的一个点。最开始我们做告警详情所有信息都是实时查的。指标嘛直接查时序库日志嘛直接查ES资产信息嘛直接查CMDB。听起来没问题现实很残酷——告警高峰期值班人员狂点详情页后端每次都要去五个系统来回拉数据页面转圈圈等着等着用户就放弃了回头还是自己开终端去查。后来我们发现问题的本质故障现场信息有时间敏感性晚一分钟查可能指标已经恢复到阈值以下了晚五分钟查日志已经被新日志刷下去了。这种情况下必须有一个快照机制在告警产生的同时把现场信息抓下来存好。于是我们给告警详情增加了一个“快照区”。告警触发时告警事件处理器会调用一个信息采集聚合器立即抓取指标区间、日志片段、进程状态和告警事件一起写入详情存储。这样无论过了多久打开这个告警看到的永远是故障发生那一刻的真实数据。当然也不是所有信息都做快照。静态资产信息允许实时去查CMDB因为机器归属、负责人这些数据变了反而应该显示最新的。所以我们的原则是动态信息做快照静态信息查最新。这个原则听起来简单实际落地后发现真的能少踩80%的坑。2.4 关联ID设计一条告警拉起整条链路详细信息的灵魂在于关联。没有关联再多的字段也只是孤岛。我们设计了一套关联ID体系。每条告警告警事件会生成全局唯一的告警ID告警对象如果是主机绑定资源实例ID如果是K8s容器或者中间件绑定对应的实例ID和所属业务ID。ID字段贯穿XNMS全链路。这样设计的好处很明显拿到一条告警按资源实例ID就能拉出这个资源过去七天的全部历史告警按业务ID就能拉出同业务下其它资源的当前状态按告警关联的TraceID前缀就能直接调日志系统查业务日志。如果再加一层“变更关联”按时间段和对象ID去变更系统查询就能知道这个资源是不是刚发过版本。我们在做关联查询的时候还做了一个很实用的功能告警相似度聚合。如果一个资源在短时间内多次触发同一条规则后台自动聚合成“连续告警”详情页只显示第一条和最新一条中间的过程折叠成统计维度展示。这样详情页不会出现几百条重复告警刷屏的惨状。3. XNMS告警详细信息的核心实现与实操链路3.1 详细信息生成的完整链路这条链路是我们整个实现的核心骨架分七个环节第一步监控采集端上报指标到时序库。Prometheus scrape到目标指标后按规则执行告警判定。第二步规则命中后Alertmanager或者我们自研的告警引擎产生告警事件事件里携带规则ID、实例标签、触发时间、当前值、阈值这些原始字段。第三步告警事件进入XNMS的消息队列Kafka。这里为什么走消息队列而不是直接同步处理因为告警产生是瞬时峰值很高的动作大促期间可能几秒钟几十条告警同步处理会拖垮告警引擎本身。走队列可以削峰还能做持久化重试。第四步详情生成消费组从Kafka拉取事件触发“现场信息采集任务”。这个任务会并发执行五个子采集查时序库抓指标区间、调日志系统抓日志片段、跑探测脚本检测端口和进程、调CMDB查资产归属、调变更系统查相关记录。第五步子采集结果汇总和原始告警事件一起组装成完整的详情数据写入详情存储。存储选型上我们用的是ES因为详情数据是文档型结构字段不固定ES的扩展性刚好。第六步前端消息推送和详情页都从ES读取详情数据。这里有一个细节前端轮询还是WebSocket我们最终选择了WebSocket推送机制告警事件产生后详情页无需刷新自动出现新数据实测比轮询快大概2到3秒。第七步用户打开详情页后如果觉得现场信息还不够可以点击“打开实时模式”此时详情页会实时去查询时序库和ES展示此刻最新的状态和快照数据形成对照。3.2 指标趋势回放时间窗口怎么选指标回放是详情里最直观也最核心的内容。用户打开一条告警第一眼要看的就是一张曲线图——从正常到异常的变化过程。时间窗口的选取有讲究。太窄只看到触发后的一小段看不出趋势。太宽带出大量无关信息图表会非常平缓异常点反而被淹没。我们实测下来推荐双窗口方案默认展示“告警前30分钟 告警后15分钟”一共45分钟跨度。这样既能看清异常的发生拐点又能看到触发后有没有自动恢复。点击可切换“近24小时概览”模式用于观察这个指标在一天内是否存在周期性波动或者阈值是不是定得太紧。采样点数量上45分钟窗口用1分钟粒度也就是45个点24小时窗口用5分钟粒度288个点。这个数据量对时序库毫无压力前端用ECharts绘制也流畅。参数上我们还做了一个自适应如果告警持续了很长时间比如超过1小时还没恢复那45分钟窗口就显得不够看了。所以我们动态计算窗口结束时间取当前时间窗口跨度取 max(45分钟, 告警持续时长)。这么个小改动让持续告警的场景终于能看清全貌了。3.3 日志片段捕获怎么抓才不犯傻日志是定位根因的另一个必需品。但日志这个东西抓不好就是灾难。第一个问题日志数据量太大。你不可能把告警对象前后一小时的所有日志都塞进详情页。所以我们做的是“定向捕获”——根据触发指标和规则里的标签分析出可能相关的关键字然后用这些关键字去ES里检索。比如CPU告警我们就抓对应主机上进程日志里包含“timeout”、“slow”、“error”的片段如果是接口TP99告警就直接抓该服务最近半小时的请求日志默认只取100条。这个定向策略让日志量可控在几百条以内用户体验非常好。第二个问题日志时间对齐。ES里的日志时间和监控指标时间经常存在偏差。原因很多——采集端时钟漂移、日志传输管道有延迟。我们做了对齐策略时间戳以采集端产生时间为准但是在展示的时候会把指标曲线的横轴和日志时间轴的零点对齐让用户直观看到“指标异常后20秒开始出现报错日志”这种因果关系。第三个问题日志中的敏感信息。详情页如果一两百人能看到日志里如果夹带了个人数据或者密钥那就是安全事故。我们的做法是加了脱敏过滤器在采集时匹配手机号、身份证、token等正则模式去做掩码处理存到ES里的就是脱敏后的内容。这条是合规底线一定不能省。3.4 详情页分层展示的落地经验前端展示是我们的重头戏页面结构上我们分了五个区域通过折叠面板和Tab做信息层级第一层告警摘要条。颜色区分级别红色代表严重、橙色代表警告。这里只显示五个字段告警标题、级别、当前状态、持续时间、认领人。一行看完判断紧急程度。第二层现场快照区。指标趋势图优先展示下面是日志片段列表。这层不需要点击任何按钮就能看到默认展开。第三层资源信息区。展示机器IP、业务归属、责任人、标签信息默认折叠需要确认影响面的时候展开。第四层关联信息区。历史告警列表、相似告警、关联变更记录。这层我们加了一个亮点功能如果历史存在同类告警就直接展示“上次出现时间”、“上次恢复方案”能极大减轻重复分析的工作量。第五层处置面板。处置按钮、认领按钮、评论框还有应急预案链接。3.5 后端接口的响应保障详情页做得再好看接口卡死也是白搭。在性能优化上我们花了几轮功夫。详情页主路径接口要求P95响应时间小于3秒。第一次压测直接爆了原因是子采集任务串行执行光日志查询就花了2秒多。我们改成并发采集后5个采集任务并行总耗时降到了1秒左右。流程很简单用Go的goroutine或者Java的CompletableFuture把五个采集操作丢到线程池并发执行然后通过Future.get统一等待结果。第二个瓶颈是ES查询。日志检索用了复杂的query_string语法个别查询走了全表扫。我们优化方案是强制限定时间范围索引按天分片查询时带上告警对象的机器标识作为filter把扫描量从百万级压到万级。第三个瓶颈在后端重复查询。同一台机器同一时间段的指标和日志在一个小时内如果你点了五条相同资源的告警每次都去查一遍完全没必要。我们做了一个Redis缓存key设计是“告警对象时间段查询类型”TTL设15分钟命中缓存直接返回。实测缓存命中之后详情页响应时间从1.2秒降到300毫秒左右。4. 高频问题与排查技巧实录4.1 详情页空白快照数据没有生成这条是我们上线初期最高频的故障。症状告警在告警列表能看到但点开详情页现场快照区一片空白只有告警基础信息。排查过程先看Kafka消费组的消费位点发现详情生成消费组存在积压。进一步看日志发现采集日志片段时偶发ES查询超时异常被我们业务代码吞掉了外部表现就是“采集任务失败字段留空”。这里暴露了两个问题一是子采集任务缺乏超时控制和失败标记二是失败后没有重试机制。解决办法给每个子采集任务增加独立超时默认3秒超时熔断采集结果增加success字段哪怕日志采集失败也要保证指标和资产信息正常返回Kafka消费组开启重试队列失败的采集任务抛给重试Topic最多重试3次超过3次后确实不重试写入失败标记便于人肉排查。这个坑让我们彻底明白了一个道理详情采集任务决不能因为某一项子任务失败就整体失败详情页哪怕只有一个字段也先返回出来页面渲染永远优先保证主体信息的可用性。4.2 告警详情里的时间比实际早了8个小时时区问题经典中的经典。症状详情页展示的指标曲线横轴时间比实际时间早了8个小时。一看就是UTC和东八区没做转换。排查过程时序库存储的时间戳是UTC前端ECharts默认也认为传入的毫秒时间戳是本地时区按理说没问题。问题出在我们详情数据组装的时候在Java服务里有一个时间格式化再解析的逻辑把时间类型转成了字符串再转回来转换过程丢失了时区信息最终存入ES的就是UTC的字符串时间。前端接口拿到的是字符串而不是时间戳就不会做时区转换了。解决办法链路里统一使用long型毫秒时间戳前端在展示时统一用dayjs格式化。去掉所有字符串形式的“yyyy-MM-dd HH:mm:ss”传递。同时再数据源头将时序查询结果的时间统一按北京时间输出保证详情页所有区域的时间口径一致。4.3 同一条告警不同人看到的详情不一样这个问题的迷惑性很强。症状运维同学反馈他和同事点开同一条告警两人看到的详情数据不一样现场快照里的指标曲线某些点数值对不上。排查过程第一反应是缓存不一致查了一圈发现没有。后来仔细比对发现他两看的是同一个告警ID但拿到的指标开始时间不同。问题出在详情生成任务执行时指标查询的起止时间是“now - 30min”动态计算的。如果采集任务在Kafka里积压了五分钟那查到的“前30分钟”其实是“前35到前5分钟”和你最初期望的时间窗口就对不上了。解决办法所有时间基准不能用消费时的当前时间必须用告警触发时间triggerTime作为锚点。指标区间查询使用triggerTime前后偏移日志也使用triggerTime做基准。这样不管任务积压多久最终生成的现场快照永远以故障发生那一刻为坐标。这个改动属于日志看半天才发现的问题改完之后详情一致性彻底解决。4.4 详情页加载慢P95超过6秒这是性能问题的综合体现。排查过程先看接口耗时分布发现大头的ES查询。查详情发现日志检索的索引范围没有按天限制用了一个字段的分词查询直接全索引扫描。再看时序查询告警对象的主机名标签匹配没有命中索引前缀走的是全扫描。优化方案从四步走ES索引查询强制增加时间范围过滤日志索引按天分片只查告警发生前后1小时对应的分片。时序查询改为以资源ID为第一索引键用过滤器先过滤资源ID再查时间范围。详情接口增加聚合缓存详情数据的各个子块分别设置不同的缓存策略指标和日志缓存5分钟资产信息缓存1小时。前端对详情页做异步分区加载不等着全部信息返回摘要条先显示现场快照逐步插进来。最终P95从6秒降到1.5秒左右核心页面秒开了。4.5 常见问题速查表问题现象可能原因排查思路解决方案详情页空白Kafka消费积压或子任务失败被吞查看消费位点和失败日志子任务独立超时重试队列时间差8小时UTC/东八区处理混乱检查存储类型是字符串还是时间戳统一毫秒时间戳展示层格式化同告警不同人看到不同用了消费时当前时间做时间窗口对比两个详情的时间基准统一以triggerTime为锚点重建快照详情页响应慢ES扫全量索引或时序查询无过滤看接口耗时分布和慢查询时间范围限制资源ID索引多级缓存日志完全抓不到关键字定向捕获规则命中率低查看ES检索结果和查询语句调整关键字规则增加fallback全量抓取最近50条资产信息显示错误实时查CMDB但CMDB数据滞后对比CMDB更新时间和告警时间调整为活动资源取快照静态信息查最新并标注时间5. 从详细信息反哺监控体系的经验沉淀5.1 告警详情是告警降噪的最好工具做完详细信息升级后我们发现了一个意想不到的价值——它成了调整告警规则的重要依据。以前调阈值靠拍脑袋阈值定高了怕漏报定低了全是告警。有了详情里的指标曲线和日志片段后我们可以直接回放每一次告警发生前后的完整现场看看到底是真故障还是误报。比如有一个业务的口径是“接口成功率低于99%就告警”但详情曲线显示成功率在99.2%和99.8%之间正常波动偶发性毛刺到了98.9%就会误触。这就是典型的阈值过紧。后来我们建立了规则调优流程每次告警降噪评审会直接打开详情页看曲线凡是高频误报的规则以两周的P99指标为依据重新定阈值。事实胜于雄辩有现场证据之后规则调整的效率翻了不止一倍。5.2 从详细信息里沉淀知识库这也是我们后续迭代的一个方向。每一条告警在完结后处理人会填写处置结论。日积月累之后这些结论就是宝贵的故障知识库。我们做了一个关联搜索功能当你打开一条新告警详情时系统自动用“告警对象类型告警规则关键日志关键字”去匹配历史告警的处理结论把相似的问题处理经验直接在详情页推给你。比如数据库连接池满的告警历史处理结论可能是“调大maxActive并重启连接池”新告警可以直接参考省去重复排查。这种体系一旦跑起来运维团队会越来越轻松。告警详情不再只是一个展示信息的页面而是整个监控运维知识的流转载体。5.3 推送消息中的精简详情设计最后分享一个我们打磨了很多版的细节——告警推送消息里的详情摘要。详情页信息全但推送消息不能全。企业微信和钉钉的消息卡片空间有限我们最终只放了五个字段告警标题、级别、受影响业务、持续时间、触发时核心指标值。然后附带一个按钮“查看详情”点击跳转Web端详情页。原本想直接把快照图也推到消息里后来因为图片生成链路复杂且推送延迟高权衡后放弃了。如果你也想做这个功能我的建议是先做文字摘要别一上来就追求图片。文字摘要成本低、稳定、推送快图片和PDF报告可以放到周期报表里做。6. 写在最后的几句实在话整个XNMS项目监控告警详细信息模块从最初的三字段裸奔到现在的快照、趋势、日志、关联、知识库五位一体前后持续了大半年时间。如果让我把这些经验浓缩成几句话我会说第一告警详细信息不是“加字段”而是“还原现场”。设计的时候先问自己故障发生时一个刚被叫醒的值班人员打开这个页面能不能在两分钟内判断要不要起床上线处理如果不能那信息架构就不及格。第二动态信息必须做快照静态信息可以查最新的。这个原则如果你记不住记住“故障现场不容错过”这句就行。后期再想补救快照就已经晚了。第三关联信息才是详情页的王牌。指标和日志是基本盘但真正让人一眼看明白的是历史告警、相似问题、变更记录这些被大多数监控系统忽略的维度。第四性能和稳定性永远优先于花哨的展示。一个详情页面如果总是转圈圈再全的信息也等于零。这次升级让我最欣慰的瞬间是一次线上真故障支付网关延迟告警弹出值班同事打开详情页看到指标曲线在故障前20分钟就有一次小幅爬升日志片段指向了上游Redis连接异常一分钟之内判断出是缓存抖动直接联系对应团队处理。整个过程没有翻终端没有查面板没有问来问去。这就是详细信息该有的样子。
返回列表