Prometheus 告警恢复时,怎么获取恢复时的值?

news/2024/9/20 13:37:58/文章来源:https://www.cnblogs.com/ulricqin/p/18387088

Prometheus 告警事件中的 $value 表示当前告警触发时的值,但是在告警恢复时,Resolved 事件中的 $value 仍然是最新告警时的值,并非是恢复时的值,这是什么原因和原理?是否有办法来解决呢?

不废话,先说原理。

原理

告警规则是配置在 prometheus.yaml 中的,由 Prometheus 负责做规则判定。Prometheus 规则判定的逻辑也很简单,就是周期性的,拿着 promql 去查询数据,如果查到了数据,并且连续多次满足 for 指定的时长,就触发告警事件,如果查不到数据,就认为指标是正常健康的状态。比如:

cpu_usage_idle < 5

如上例,告警规则的 promql 中是带有阈值(< 5)的,所以只要查到了数据,就说明当前的值小于 5,只要没查到数据,就说明当前的值大于等于 5,即当前数据是健康的状态。注意,查不到数据的时候,时序库不返回数据,换句话说,数据正常的时候,因为时序库不返回数据,上层就拿不到正常状态时的值,既然拿不到正常状态时的值,也就没法在恢复时展示当前最新的值啦。

实际上,恢复时的事件,是 Alertmanager 根据 resolve_timeout 生成的,而不是 Prometheus 生成的。Alertmanager 生成恢复事件时,会把上次告警的标签和注解带过去,值呢?就是上次告警时的值,Alertmanager 不会再去查询 Prometheus 拿到最新的值。

Alertmanager 可以拿到恢复时的值么?

坦白讲,很难。Alertmanager 需要根据上次告警的标签和注解去查询 Prometheus 拿到上次告警时的值,Alertmanager 不会这么干的,核心是:

  • 从职能上,Alertmanager 去查询 Prometheus,就反向依赖了,Alertmanager 是告警的分发中心,不止是接收 Prometheus 推送过来的事件,还会接收其他告警源推送过来的事件,如果 Alertmanager 要去查询 Prometheus,那就耦合太过严重。
  • Prometheus 的告警规则中可以附加标签,和监控指标的标签一起,作为事件的标签集发给 Alertmanager,Alertmanager 需要根据这些标签去查询 Prometheus,拿到原始数据,这在某些场景下是不可行的。一个是要把标签中的附加标签剔除,只留数据标签,Alertmanager 没有办法做到;其次,有些 promql 查询结果压根就没有标签,根本没法查;再次,Alertmanager 需要解析 promql,把阈值的部分拿掉,而有些 promql 压根就不是数字阈值。

如果你想通过修改 Alertmanager 达成所愿,放弃吧。

有没有办法解决?

有。通常的解决办法有两种:

  • 告警规则里,顺便配置恢复时的 promql
  • 把阈值从 promql 中拿掉,promql 只用于查询原始数据,然后在上层做阈值判定,不管监控指标当前是否健康,都会查到原始数据

下面我以一些监控产品为例,具体来说明。

告警规则里配置恢复时的 promql

使用这个方法的产品,以夜莺(Nightingale)监控为例,来讲解具体做法。核心是配置两个地方,一个是在告警规则里配置恢复时的 promql,另一个是在告警模板里配置恢复时的值的渲染。

比如我有一个告警规则用来侦测 HTTP 地址探测失败:

夜莺告警恢复时拿到恢复时的值-告警时的promql

需要在告警规则最下面的自定义字段里,增加 recovery_promql 的配置,如下:

recovery_promql

要理解这个工作逻辑,我们先来看看 http_response_result_code 这个指标的数据长什么样子:

夜莺告警恢复时拿到恢复时的值-即时查询

从上图可以看出,这个指标包含两个 series,其中 agent_hostname 和 method 字段相同,target 字段可以区分开这俩 series。告警规则 http_response_result_code != 0 如果触发,告警事件中一定会带有 target 标签,所以,如果告警事件恢复的时候,我们用高警时的那个 target 标签去查询,一定就可以准确查到恢复时的值了。所以 recovery_promql 的配置中引用了 target 标签,其值是变量,这个变量就是告警事件中的 target 标签值。

然后,我们在告警模板里,增加一个恢复时的值的渲染,以钉钉模板为例:

#### {{if .IsRecovered}}<font color="#008800">💚{{.RuleName}}</font>{{else}}<font color="#FF0000">💔{{.RuleName}}</font>{{end}}---
{{$time_duration := sub now.Unix .FirstTriggerTime }}{{if .IsRecovered}}{{$time_duration = sub .LastEvalTime .FirstTriggerTime }}{{end}}
- **告警级别**: {{.Severity}}级
{{- if .RuleNote}}
- **规则备注**: {{.RuleNote}}
{{- end}}
{{- if not .IsRecovered}}
- **当次触发时值**: {{.TriggerValue}}
- **当次触发时间**: {{timeformat .TriggerTime}}
- **告警持续时长**: {{humanizeDurationInterface $time_duration}}
{{- else}}
{{- if .AnnotationsJSON.recovery_value}}
- **恢复时值**: {{formatDecimal .AnnotationsJSON.recovery_value 4}}
{{- end}}
- **恢复时间**: {{timeformat .LastEvalTime}}
- **告警持续时长**: {{humanizeDurationInterface $time_duration}}
{{- end}}
- **告警事件标签**:
{{- range $key, $val := .TagsMap}}
{{- if ne $key "rulename" }}- `{{$key}}`: `{{$val}}`
{{- end}}
{{- end}}

这里最为关键的逻辑是判断 .AnnotationsJSON.recovery_value 的逻辑:

{{- if .AnnotationsJSON.recovery_value}}
- **恢复时值**: {{formatDecimal .AnnotationsJSON.recovery_value 4}}
{{- end}}

如果 .AnnotationsJSON 中包含 recovery_value 就展示,展示的时候把 recovery_value 保留 4 位小数。这个 .AnnotationsJSON 是夜莺告警规则中的自定义字段部分,如果告警事件中有恢复时的值,就会在这个字段中体现。

最终效果如下:

夜莺告警恢复时拿到恢复时的值-最终效果

把阈值从 promql 中拿掉,promql 只用于查询原始数据

使用这个做法的产品,以 FlashDuty 举例,FlashDuty 不但支持类似夜莺这样的配置 recovery_promql 的方式,还支持 promql 中不带阈值的方式。我们重点讲解 promql 中不带阈值的方式。

以 Memcached 的某个告警规则举例,查询条件里不写阈值,判定规则里写阈值,如下图所示:

夜莺告警恢复时拿到恢复时的值-FlashDuty规则

这种方式需要先查到当前值,再拿着当前值去做判定,所以不管是告警时还是恢复时,都可以拿到当前值。这种方式非常直观,大部分场景都适用。对于一个查询条件过滤到很多时序的场景,这种方式会查到特别多的数据,对告警引擎也是个压力。需要斟酌。

如果你也想让自己的监控系统支持在恢复时拿到恢复时的值,可以参考上述两种方式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/789200.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI 网关零代码解决 AI 幻觉问题

本文将以高德地图和心知天气两个服务为例,介绍一下如何零代码使用 AI Agent 插件构建一个同时支持地图服务和天气服务的 Agent,同时会探讨 AI Agent 插件的实现原理。作者:邢云阳,Higress Contributor 前言 什么是 AI Agent 随着大模型技术的快速发展,越来越多的公司在实际…

ollama 最快方式部署管理大模型

github:https://github.com/ollama/ollama 模型地址:https://ollama.com/library/llama3.1 linux: 安装 1.下载安装脚本 curl -fsSL https://ollama.com/install.sh | sh 2.修改启动环境变量 如果是root 用户记得改为rootvim /etc/systemd/system/ollama.service[Unit] Descrip…

荣誉+1 !入选十大科技领先成果!

8月28日,2024中国国际大数据产业博览会(简称“数博会”)在贵阳市隆重开幕,本届展会以“数智共生:开创数字经济高质量发展新未来”为主题,全方位、多角度展示国内外数据产业最新动态、最新成果和发展趋势。8月28日,2024中国国际大数据产业博览会(简称“数博会”)在贵阳…

Linux通用性-日志切割脚本

一、公司提供的参考脚本: #!/bin/bash # 定义需要清理的文件 log_file=( "/mpjava/ly.mp.dfpv.acc.biz/bin/nohup.out" "/mpjava/ly.mp.dfpv.acc.service/bin/nohup.out" ) # 获取当天日期 date_now=$(date +%Y%m%d)for file_dir in $log_file do# 获取文…

Redis十大数据类型

Redis十大数据类型 数据类型一般指的是 value 的数据类型,key的类型一般都是字符串 一、总体概述redis字符串(String)string是redis 最基本的类型,一个key对应一个value,string类型是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象 一个…

【转载】启发式合并

https://zhuanlan.zhihu.com/p/560661911 数据结构学习笔记(8) 启发式合并 启发式合并是用来解决子树中的统计问题。在codeforces上叫做dsu on tree(树上启发式合并)。这里我们主要是来讲在树上进行启发式合并。实际上之前我有讲过启发式合并严格鸽:启发式合并 看似暴力实则很…

利用通义灵码实现我的第一次开源贡献

作者:重庆邮电大学计算机学院李逸雄 结缘开源 最早了解开源是从学校的兴趣组织开始的。2023 年 10 月 21 日,openSUSE 亚洲峰会在我们学校召开,这次会议汇聚了许多来自 openSUSE 社区贡献者以及对开源感兴趣的爱好者们。我第一次知道有这么多志同道合的爱好者在进行开源贡献…

腾讯云域名托管到 cloudflare

cloudflare https://dash.cloudflare.com/ 腾讯云域名列表 https://console.cloud.tencent.com/domain/all-domain/all 先进入 腾讯云列表,点击自己已购买的域名点击修改; https://console.cloud.tencent.com/domain/all-domain/all修改为cloudflare提供的, 如下: 进入 htt…

中间件实时监控,运维难题一站解决

智和信通方案通过构建对Tomcat、Jboss、WebLogic等中间件的关键指标的监控,实现对中间件性能和资源的实时追踪,识别并解决影响中间件性能的问题,保障中间件的高性能及高可用性,更全面地支撑业务及应用的稳定、持续运行,提升用户体验。 中间件是介于操作系统和在其上…

【性能优化+数据库】读写分离方案

读写分离是一种常见的优化方案,旨在通过将读操作、和写操作分开,如下图所示:大致的原理,如下: 【主库(Master)】:负责处理所有的写操作(比如:插入、更新、删除......)、和写操作相关的事务;【从库(Slave)】:负责处理读操作(查询),通过主从复制机制从主库同步…

【性能优化+数据库】读写分离

读写分离是一种常见的优化方案,旨在通过将读操作、和写操作分开,如下图所示:大致的原理,如下: 【主库(Master)】:负责处理所有的写操作(比如:插入、更新、删除......)、和写操作相关的事务;【从库(Slave)】:负责处理读操作(查询),通过主从复制机制从主库同步…

VL25 输入序列连续的序列检测

这个题目的意思是输入是单bit脉冲,然后当8个周期的脉冲序列符合给定的参数值则match输出1; 因此肯定需要一共8位的寄存器存储总共8个a的输入脉冲 此外由于是从左向右匹配,因此每个周期输入的a要从寄存器最低位输入,从右向左移位(temp_a<={temp_a[6:0],a};),这样才是输…