普罗米修斯的增加()有时会使价值增加一倍:如何避免?

san*_*mai 12 prometheus

我发现对于某些图表,我从普罗米修斯得到的双打值应该只是:

图表与上面的两个酒吧

查询我使用:

increase(signups_count[4m])
Run Code Online (Sandbox Code Playgroud)

刮擦间隔设置为建议的最大值 2分钟.

如果我查询存储的实际数据:

curl -gs 'localhost:9090/api/v1/query?query=(signups_count[1h])'

"values":[
     [1515721365.194, "579"],
     [1515721485.194, "579"],
     [1515721605.194, "580"],
     [1515721725.194, "580"],
     [1515721845.194, "580"],
     [1515721965.194, "580"],
     [1515722085.194, "580"],
     [1515722205.194, "581"],
     [1515722325.194, "581"],
     [1515722445.194, "581"],
     [1515722565.194, "581"]
],
Run Code Online (Sandbox Code Playgroud)

我看到只有两次增加.事实上,如果我查询这些时间,我会看到预期的结果:

curl -gs 'localhost:9090/api/v1/query_range?step=4m&query=increase(signups_count[4m])&start=1515721965.194&end=1515722565.194'

"values": [
     [1515721965.194, "0"],
     [1515722205.194, "1"],
     [1515722445.194, "0"]
],
Run Code Online (Sandbox Code Playgroud)

但是Grafana(以及GUI中的普罗米修斯)倾向于step在查询中设置不同,对于不熟悉普罗米修斯内部工作的人,我会得到一个非常意外的结果.

curl -gs 'localhost:9090/api/v1/query_range?step=15&query=increase(signups_count[4m])&start=1515721965.194&end=1515722565.194'

... skip ...
 [1515722190.194, "0"],
 [1515722205.194, "1"],
 [1515722220.194, "2"],
 [1515722235.194, "2"],
... skip ...
Run Code Online (Sandbox Code Playgroud)

知道这increase()只是函数的特定用例的语法糖rate(),我想这是应该如何工作的情况.

如何避免这种情况?我如何让Prometheus/Grafana给我看一些,两次两次,大部分时间?除了通过增加刮擦间隔(这将是我的最后手段).

我知道普罗米修斯不是一种精确的工具,所以如果我不是在任何时候都有一个好的数字,但大部分时间都可以.

我还缺少什么?

bri*_*zil 12

这称为混叠,是信号处理中的基本问题.您可以通过提高采样率来改善这一点,4米范围有点短,2米范围.尝试10米范围.

例如,在1515722220执行的查询仅查看580@1515722085.194和581@1515722205.194样本.这是2分钟内增加1,超过4分钟的推断是增加2 - 这是预期的.

如果您希望100%准确,您需要日志,任何基于指标的监控系统都会有类似的工件.

  • 这个声明“任何基于指标的监控系统都会有类似的工件,如果你想要 100% 的准确性,你需要日志。” 事实上,这是不正确的,这不仅是 Prometheus 所独有的,而且许多人已向 Prometheus 提交了错误,并提出了针对此问题的修复方案。 (3认同)

Ali*_*ean 8

increase() 将始终(大约)使您的设置实际增加一倍。

原因是(目前已实施):

  1. increase()是(正如您所观察到的)语法糖,rate()即它是将返回的值rate()乘以您指定范围内的秒数。在你的情况下,它是rate() * 240
  2. rate()在计算中使用外推法。在绝大多数情况下,4 分钟的范围将正好返回 2 个数据点,几乎正好相隔 2 分钟。然后计算该比率为最后一个和第一个之间的差异(即您的情况下的 2 分)除以 2 分的时间差(在 99.99% 的情况下约为 120 秒)乘以您请求的范围(正好是 240 秒) )。因此,如果 2 点之间的增加为零,则比率为零。如果 2 点之间的增加为1.0,则计算结果rate()将接近2.0 / 240,因此increase()将是2.0

这种方法对于平稳增加的计数器非常有效(例如,如果您每 2 分钟或多或少有固定的注册数量)。但是对于很少增加的计数器(就像您的注册计数器一样)或尖峰计数器(例如 CPU 使用率),您会得到奇怪的高估(例如您看到的增加 2)。

您基本上可以对普罗米修斯的实现进行逆向工程,(requested_range - scrape interval)并通过乘以和除以得到(非常接近)实际增加requested_range,基本上是回溯普罗米修斯所做的外推。

在你的情况下,这意味着

increase(signups_count[4m]) * (240 - 120) / 240
Run Code Online (Sandbox Code Playgroud)

或者,更简洁地说,

increase(signups_count[4m]) / 2
Run Code Online (Sandbox Code Playgroud)

它要求您同时了解范围的长度和刮擦间隔,但它会给您想要的:“大多数情况下,一个对一个,两个对两个”。有时您会得到1.01而不是1.0因为刮擦相隔 119 秒,而不是 120 秒,有时,如果您的评估与刮擦密切相关,则边界上的某些点可能包含或不包含在数据点计算中,但它仍然是比 更好的答案2.0

  • 这不是一个好的建议,因为它假定正好有 2 个样本总是在范围内。首先,这对失败的刮擦没有弹性,因为它仍在使用太低的范围。其次,它对您不能依赖的刮擦的相位和抖动进行假设,并可能导致答案比应有的大得多。 (2认同)
  • 大多数情况下,它假定恰好有 2 个样本位于该范围内。这正是OP所要求的:“大多数时候,一个对一个,两个对两个。而普通的rate()/increase()在相位和抖动方面有完全相同的问题:它们会产生更大的答案超出了它们应有的范围(更不用说它们已经产生的答案是平均情况下应有的两倍了。 (2认同)