← 中文资源

简体中文版本

判断告警何时应当触发

在一段指标序列上评估阈值规则,要求阈值连续被突破若干分钟之后才真正触发告警。

阅读英文原文

任务

对给定的指标序列逐分钟评估阈值规则:只有连续满足持续时长要求时才触发,并报告首次突破发生在哪一分钟。

契约

  • 输入:JSON 对象:{ rule: { threshold, comparison, forMinutes }, series: [{ minute, value }] }
  • 输出:JSON 对象:{ firing: boolean, firstBreachMinute: number | null }

样例

  1. 输入 {"rule":{"threshold":0.05,"comparison":"above","forMinutes":3},"series":[{"minute":1,"value":0.01},{"minute":2,"value":0.06},{"minute":3,"value":0.07},{"minute":4,"value":0.08}]} -> 期望 {"firing":true,"firstBreachMinute":2}。第 2 到第 4 分钟连续三次突破阈值。
  2. 输入 {"rule":{"threshold":0.05,"comparison":"above","forMinutes":3},"series":[{"minute":1,"value":0.06},{"minute":2,"value":0.04},{"minute":3,"value":0.06}]} -> 期望 {"firing":false,"firstBreachMinute":null}。中间出现一次健康样本使连续计数重置,因此始终没有攒够三次。

参考实现

function solve({ rule, series }) {
      const breach = (value) => (rule.comparison === 'above' ? value > rule.threshold : value < rule.threshold);
      let streak = 0;
      let firstBreachMinute = null;
      for (const point of [...series].sort((a, b) => a.minute - b.minute)) {
        if (breach(point.value)) {
          if (streak === 0) firstBreachMinute = point.minute;
          streak += 1;
          if (streak >= rule.forMinutes) return { firing: true, firstBreachMinute };
        } else {
          streak = 0;
          firstBreachMinute = null;
        }
      }
      return { firing: false, firstBreachMinute: null };
    }

为什么有效

没有持续窗口的告警会因为单个样本就发页。要求连续突破可以滤掉大部分单点噪声,同时仍让真实故障可见。

一个未突破的样本会把连续计数清零,并清空首次突破分钟。