2 min read
准确计算Prometheus Counter增量

需求

数据输入为 counter 类型的指标 demo_tasks__count

实现方式:increase(...)​ 函数计算某个时段的增量,如 increase(demo_tasks__count[5m])​ 计算 5min 内的增量,且会处理 counter 置零的场景

问题

increase() ​函数计算结果经常为小数,且与实际该时段内的任务增量不同

初步调研

Prometheus 做 rate 计算时会进行外推 extrapolation,导致出现小数

见讨论:

Prometheus 官方专门写了一篇 blog 解释 rate 的计算过程,值得仔细阅读:Blog - How Exactly Does PromQL Calculate Rates?

Take-away

  1. Prometheus 进行 rate 计算时会进行外推 extrapolation,产生小数
  2. Prometheus PromQL 当前不适合进行整数类的数据统计,如一段时间的请求数、任务数,Victoria Metrics 可以

尝试解决方案

从邮件组讨论中得到一个神秘公式 https://groups.google.com/g/prometheus-users/c/DhoigmwGx5Q/m/5s3My1EzBAAJ

increase(metric[5m + scrape_interval]) * 5m / (5m + scrape_interval)​​​​

套用在现有的数据里测试,发现可以工作!

为什么该公式可以工作

increase(metric[5m + scrape_interval]) * 5m / (5m + scrape_interval)

  1. 先看 Prometheus 的 rate 计算过程 Blog - How Exactly Does PromQL Calculate Rates?

    为了得到区间内的数值增量,一个简单的想法是 increase(metric[5m]) / 5m * (5m - scrape_interval)​​​

  2. increase(metric[5m]) / 5m * (5m - scrape_interval)​​​有致命性问题,也是 Prometheus 试图通过外推去弥补的:丢失区间中的差值

  3. 我们需要算出来的是当前区间及之前的 1 个 datapoint 的差值!这也正是 Victoria Metrics increase 的实现方案

    通过加上 1 个 scape_interval metric[5m + scrape_interval]​​​,可以涵盖区间前一个点,于是产生了公式 increase(metric[5m + scrape_interval]) * 5m / (5m + scrape_interval)​​​

    5m​ ​指 step interval

  4. 还有遗漏的地方吗?extrapolation 的两类特殊情况,这两种情况是否影响该公式的准确性?

    1. 指标在 time window 内开始或结束:the extrapolation only extends half an average sample interval toward the window boundary
    2. 负值不会外推:extrapolation only happens until the expected 0​​​ value is hit

扩展阅读

  1. 为什么 Victoria Metrics 的 increase 可以得到整数 VictoriaMetrics: PromQL compliance - Roman Khavronenko - Medium
  2. Design doc: Prometheus x-rate - Extended rate(), increase() and delta()