普罗米修斯查询最后一个局部峰值

Prometheus query for last local peak value

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

局部峰值是大于其上一个和下一个数据点的点。 (所以当前时间肯定不是局部高峰)

(p: 峰值点, i: cornjob 间隔, m: 错过执行)

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

使用 z-score 检测异常

如果您知道系列的平均值和标准偏差 (σ),则可以使用系列中的任何样本来计算 z 分数。 z 得分以与平均值的标准差数来衡量。所以 z 分数为 0 意味着 z 分数与具有正态分布的数据集中的平均值相同,而 z 分数为 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 范围的值都是异常值。 例如,当我们的聚合超出此范围超过五分钟时,您会收到警报。

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

时才为真(即 > 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:]) 开销很大,引入记录规则有助于提高性能,尤其是在仪表板中。

此外,在您的情况下,也可以使用自上次二阶导数非零以来的时间,因为当作业 starts/finishes(图中的下降,或者当它开始上升)。