prometheus - 正确检测 Prometheus 计数指标的变化
问题描述
我试图编写一个 PromQL 查询来检测计数指标的变化。
我的抓取间隔是 15 秒。
我这样查询指标:
http_server_requests_seconds_count{outcome!="REDIRECTION",outcome!="SUCCESS"}
它显示了有多少http_server_requests
不是重定向并且没有成功。
我尝试使用此指标编写警报表达式如下所示:
sum by(service, method, outcome, status, uri) (
rate(
http_server_requests_seconds_count{
outcome!="REDIRECTION",
outcome!="SUCCESS"
}[1m]
)
) * 60
我的想法是 [1m] 乘以 60 秒的速率将是1
发生变化时,但据我所知,我得到了2
?
这些图表清楚地表明了这一点:
上图是求和表达式,下图是服务器请求计数的变化。当底部图计数 +1 时,顶部图也应该暂时上升1
(但实际上它上升到2
)。
我究竟做错了什么?我是不是误会了什么?如何编写一个查询,1
在发生更改时为我提供值?我应该期望能够编写这样的查询吗?
谢谢!
解决方案
这是因为 Prometheus 优先考虑范围的一致定义而不是准确性。即它总是将范围定义为落在(包含)区间[now() - range, now()] 内的所有样本。这个定义对仪表非常有意义:如果你想计算avg_over_time()
一个时间范围等于步长的,你希望每个输入样本都包含在恰好一个输出样本的计算中。
但对于柜台来说,情况并非如此。在时间范围等于步长的情况下,一个输入值(即两个连续样本之间的增量)基本上被丢弃。(有关更多详细信息,请参阅 Prometheus 问题#3746和3806。)为了弥补它丢弃的数据,Prometheus 使用外推法来调整计算结果。
这意味着如果(如您的情况)您使用的时间范围是您的刮擦间隔的 2 倍(刮擦间隔的1m
范围30s
),Prometheus 将(平均)在每个范围内找到 2 个样本,但这 2 个样本所涵盖的实际时间范围将待在身边30s
。因此,Prometheus 将1m
通过将值加倍来帮助将速率推断为请求的值。因此结果是 2 而不是预期的 1。您还会注意到,由于连续样本之间的一些增加被丢弃(即使没有样本),并不是您的计数器中的所有增加都显示在您的rate()
图表中。(即没有跳转rate()
对应于第三次计数器增加。如果你在不同的时间刷新,不同的增加会出现和消失。Grafana 通过始终将请求的范围与步骤对齐来“解决”后者,因此始终缺少相同的增加。)
Prometheus 开发人员建议的解决方案是计算更长持续时间的费率。但所做的只是减少误差(你会得到 1.5 与 3x 范围,1.33 与 4x 范围,1.25 为 5x 范围等),永远不会摆脱它。普罗米修斯的推断被平稳地增加计数器隐藏得足够好,但像你自己的计数器一样突出,很少增加。)
这个问题的唯一解决方法(没有修复 Prometheus,我已经为此提交了 PR 并正在维护一个 fork)是对 Prometheus 的rate()
. 即假设一个30s
表达式的抓取间隔rate(foo[1m])
应该替换为:
rate(foo[90s]) * 60 / 90
或更一般地(注意括号内的表达式需要是时间文字,不能是计算)
rate(foo[intended_range + scrape_interval]) * intended_range / (intended_range + scrape_interval)
这样做的原因是该intended_range + scrape_interval
范围将为您提供足够的样本来覆盖 的增加intended_range
,这就是您想要的。但是随后您必须撤消 Prometheus 的推断引入的变化,因此随之而来的乘法和除法。这是一个丑陋的黑客,取决于你知道你的抓取间隔并将其硬编码到你的记录规则和/或 Grafana 查询中。
请注意,无论您使用哪种方法,您都可能不会得到正好为 1 的值。由于服务、网络和内部 Prometheus 延迟,样本通常不会在毫秒内对齐,因此每秒的增长率会略低于或略高于预期值。
推荐阅读
- node.js - 引导表单 - 将表单数据保存到数组中
- python-3.x - 如何在 django 频道中为不同用户在同一组上发送不同的消息
- python - 如何使用 python 从仅包含斜杠的 url 中提取参数?
- python - Knime,回归分析的相关节点(统计模型)
- python - 用于数字输入的 Python 类型提示
- reactjs - GraphQL:variableValues 中的意外变量:首先在 args 中不使用变量时
- c# - 如何删除 DataGridView 最后一行 ButtonColumn 按钮 c#?
- amazon-web-services - aws api 部署中的端点 url 是什么?
- macos - MacOS Instruments 返回 CPU 周期的空配置文件
- c# - 遍历字典值