正确检测 Prometheus 计数指标的变化

Eri*_*vic 3 prometheus promql

我尝试编写 PromQL 查询来检测计数指标的变化。

我的抓取间隔是 15 秒。

我像这样查询指标:

http_server_requests_seconds_count{outcome!="REDIRECTION",outcome!="SUCCESS"}
Run Code Online (Sandbox Code Playgroud)

它显示了所有http_server_requests未重定向且未成功的总数。

我使用此指标编写警报表达式的尝试如下所示:

sum by(service, method, outcome, status, uri) (
  rate(
    http_server_requests_seconds_count{
      outcome!="REDIRECTION",
      outcome!="SUCCESS"
    }[1m]
  )
) * 60
Run Code Online (Sandbox Code Playgroud)

我的想法是 [1m] 乘以 60 秒的速率将是1发生变化时,但据我所知,我得到2?

这些图表清楚地表明了这一点:

普罗米修斯图

上图是求和表达式,下图是服务器请求计数的变化。当底部图形计数 +1 时,顶部图形也应该暂时上升1(但实际上它上升到2)。

我究竟做错了什么?我是不是误会了什么?如何编写一个查询,1在发生更改时为我提供值?我应该期望能够编写这样的查询吗?

谢谢!

Ali*_*ean 6

这是因为 Prometheus 优先考虑范围是什么的一致定义而不是准确性。即它总是将范围定义为落在(包括)区间 [now() - range, now()] 内的所有样本。这个定义对于仪表来说非常有意义:如果你想计算avg_over_time()一个时间范围等于步长的 ,你希望每个输入样本都包含在恰好一个输出样本的计算中。

但对于计数器而言,情况并非如此。在时间范围等于步长的情况下,一个输入值(即两个连续样本之间的增加)基本上被丢弃。(更多细节请参见 Prometheus 问题#37463806。)为了弥补它丢弃的数据,Prometheus 使用外推法来调整计算结果。

这意味着如果(如您的情况)您使用的时间范围是您的抓取间隔(抓取间隔1m范围30s)的 2 倍,Prometheus 将(平均)在每个范围内找到 2 个样本,但是这 2 个样本涵盖的实际时间范围将在附近30s。因此,普罗米修斯将1m通过将值加倍来帮助将速率外推到请求的速率。因此,结果是 2 而不是预期的 1。您还会注意到,因为连续样本之间的某些增加被丢弃(即使没有样本),并不是您的计数器中的所有增加都显示在您的rate()图表中。(即没有跳转rate()对应第三次计数器增加。如果你在不同的时间刷新,不同的增加会出现和消失。Grafana 通过始终将请求的范围与步骤对齐来“解决”了后者,因此始终缺少相同的增加。)

Prometheus 开发人员建议的解决方案是计算更长持续时间的费率。但所做的只是减少错误(3 倍范围内为 1.5,4 倍范围内为 1.33,5 倍范围内为 1.25,等等),永远不会摆脱它。普罗米修斯的推断通过平稳增加计数器被隐藏得很好,但像你自己的计数器一样突出,就像一个疼痛的拇指,很少增加。)

这个问题的唯一解决方法(没有修复 Prometheus,我已经提交了一个 PR 并且正在维护一个 fork)是对 Prometheus 的rate(). 即假设30s表达式的刮取间隔rate(foo[1m])应替换为:

rate(foo[90s]) * 60 / 90
Run Code Online (Sandbox Code Playgroud)

或更一般地(注意括号内的表达式需要是时间文字,不能是计算)

rate(foo[intended_range + scrape_interval]) * intended_range / (intended_range + scrape_interval)
Run Code Online (Sandbox Code Playgroud)

这样做的原因是该intended_range + scrape_interval范围将为您提供足够的样本来覆盖超过 的增加intended_range,这正是您想要的。但是随后您必须撤消 Prometheus 的外推法引入的更改,因此需要进行乘法和除法。这是一个丑陋的黑客,取决于您知道您的抓取间隔并将其硬编码到您的记录规则和/或 Grafana 查询中。

请注意,无论您使用何种方法,您可能都不会得到恰好为 1 的值。 由于服务、网络和内部 Prometheus 延迟,样本通常不会以毫秒为单位对齐,因此每秒的增长率会略低于或略高于预期值。