Prometheus 查询最后一个本地峰值

问题描述

什么 Prometheus 查询 (PromQl) 可用于识别图表中最后 X 分钟的最后一个局部峰值?

局部峰值是一个大于其前一个和下一个数据点的点。 (所以当前时间绝对不是本地高峰)

sample graph

(p: 峰值点,i: 玉米作业间隔,m: 错过执行)

我希望这个值在执行 cron 作业时发现异常。正如您在图片中看到的,我编写了一个查询来计算自上次执行作业以来经过的时间。现在要设置警报规则来计算从上次成功执行开始所用的时间并找到错过的执行,我需要在该时间间隔内最后一次执行作业的时间。这个间隔对于查询来说是未知的(换句话说,作业的间隔是由另一个程序指定的),所以我无法将经过的时间与固定时间进行比较。

解决方法

使用 z-score 检测异常

如果您知道一个系列的平均值和标准差 (σ),您可以使用该系列中的任何样本来计算 z 分数。 z 分数以与平均值的标准差数来衡量。因此,z-score 为 0 意味着 z-score 与具有正态分布的数据集中的平均值相同,而 z-score 为 1 则与平均值相差 1.0 σ,依此类推。

  1. 使用大样本数据计算指标的平均值和标准偏差。
# Long-term average value for the series
- record: job:cronjob_duration_time_seconds_count:rate10m:avg_over_time_1w
expr: avg_over_time(sum(rate(cronjob_duration_time_seconds_count[10m]))[1w:])

# Long-term standard deviation for the series
- record: job:cronjob_duration_time_seconds_count:rate5m:stddev_over_time_1w
expr: stddev_over_time(sum(rate(cronjob_duration_time_seconds_count[10m]))[1w:])
  1. 获得聚合的平均值和标准偏差后,计算 Prometheus 查询的 z 分数。
# Z-Score for aggregation
(
job:cronjob_duration_time_seconds_count:rate10m -
job:cronjob_duration_time_seconds_count:rate10m:avg_over_time_1w
) /  stddev_over_time(sum(rate(cronjob_duration_time_seconds_count[10m]))[1w:])

根据正态分布的统计原理,您可以假设任何落在大致 +1 到 -1 范围之外的值都是异常。例如,您可以获得警报当我们的聚合超出此范围超过五分钟时。

,

如果您想要的是在经过的时间超过固定持续时间时触发警报,您​​可以根据 up 表达式设置类似于 changes > 0 警报的警报,这仅在作业运行时为真(即 > 0)。

一个例子是:

  rules:
  - alert: CronJobNotRunning
    expr: |
        changes(
            sum(
                rate(
                    cronjob_duration_time_seconds_count{
                        status="ok",namespace="<namespace>",exported_job="<job>"
                    }[1m]
                )
            )[1m:]
        ) == 0
    for: <alert_duration>

请注意,子查询 ([1m:]) 的开销很大,在那里引入记录规则有助于提高性能,尤其是在仪表板中。

此外,在您的情况下,也可以使用自上次二阶导数非零以来的时间,就像作业开始/完成时发生的那样(图中的下降,或开始上升时) .