# 判定周期与恢复

规则上的四个时间字段——执行频率、持续时长、留观时长、恢复判定——共同决定事件何时产生、何时恢复、何时重复通知。

最后校对于 2026-10-10

这页办完你会得到：能有意识地设规则上那四个时间字段，而不是一路默认； 并且分得清哪几个决定「事件存不存在」，哪几个只决定「消息发不发」。

这些字段背后的状态机在[判定、恢复与状态变化](https://n9e.github.io/zh/docs/concepts/evaluation.md)里讲。 这一页讲的是字段本身。

## 四个字段分别在哪儿[​](#四个字段分别在哪儿 "四个字段分别在哪儿的直接链接")

| 字段           | 步骤                  | 默认         |
| -------------- | --------------------- | ------------ |
| 执行频率       | 第 3 步，查询列表下面 | `@every 60s` |
| 持续时长 (s)   | 第 3 步，紧挨着       | 60           |
| 留观时长（秒） | 第 4 步 通知配置      | 0            |
| 启用恢复通知   | 第 4 步 通知配置      | 开           |

## 执行频率[​](#执行频率 "执行频率的直接链接")

秒级精度的 cron 表达式。常见写法是 `@every 30s`；下拉里给了常用间隔， 需要「每天 09:00」这种也可以写标准 cron。

有两条约束，方向正好相反：

* **别跑得比数据来得还快。** Categraf 默认 15 秒采一次。5 秒判一次只是把同样的三个点 重读一遍，负载翻三倍，一点收益没有。
* **别跑得比你能容忍的发现时间还慢。** 执行频率是发现时间的下限，持续时长还要往上加。

还有一条，很多人是花了代价才发现的：执行频率是**按数据源算的**。一条匹配十个实例的规则设成 `@every 15s`，一小时就是 2400 次查询。放宽数据源筛选会悄悄把这个数乘上去—— 见[按业务组与数据源划定范围](https://n9e.github.io/zh/docs/alerting/scope.md)。

SQL 类规则还要拿执行频率和语句本身的耗时对一下。跑一次要八秒的查询，别设 15 秒一跑。

## 持续时长[​](#持续时长 "持续时长的直接链接")

条件要连续成立多久才产生事件。`0` 表示第一次命中就报。

它是按序列判的：同一条序列要在连续几次判定里都被返回，直到累计时间覆盖持续时长； 只出现过一次就消失的序列永远不会产生事件。而因为压根没产生过事件， 它也不会产生恢复——一个抖动的指标配上持续时长之后是真的安静，不是被悄悄去重了。

几条经验：

* **0**：留给二元、没有歧义的东西——进程没了、证书过期了。
* **2～3 个执行周期**：留给一切采样出来的量——CPU、内存、延迟、错误率。这是最常见的情况， 也是默认值为什么是 60 秒执行频率配 60 秒持续时长。
* **比这东西自愈时间还长**：如果一个队列两分钟就自己排空了，两分钟的持续时长意味着 你永远不会知道那些能自己排空的。

发现时间大致是 `持续时长 + 一个执行周期`。按这个算预算。

## 留观时长[​](#留观时长 "留观时长的直接链接")

判定恢复之前的观察窗口。默认 `0`——条件一不成立就恢复。

告警抖动的时候就该动这个字段。设成 300 之后，条件不再成立时规则会继续盯五分钟； 这期间条件又成立了，什么都不会发生，告警就保持在告警中。

注意它到底管的是什么：**这个窗口里根本不产生恢复事件**。告警在事件列表里仍然是活跃的， 不只是安静。对一个来回横跳的指标来说，这通常才是诚实的呈现。

## 恢复到底是怎么判的[​](#恢复到底是怎么判的 "恢复到底是怎么判的的直接链接")

对 Prometheus 类规则，恢复只有一个含义：**查询不再返回那条序列了**。 因为阈值写在 PromQL 里，一条序列掉回阈值以下就不再被返回， 这和 exporter 挂掉在结果上没法区分。两种情况都会让告警恢复。

日志类和 SQL 类规则的阈值判定是在夜莺里做的，不在数据源里，所以它们能分清这两件事， 于是在每条判定条件上多出一个**恢复条件**下拉：

| 选项                               | 什么时候恢复                           | 查询查不到数据时 |
| ---------------------------------- | -------------------------------------- | ---------------- |
| 查不到数据就恢复                   | 条件不再成立，**或**查询没返回任何东西 | 恢复             |
| 必须查到数据且不满足告警条件才恢复 | 查到了一行，且这行不满足条件           | **继续告警**     |
| 结果满足自定义条件才算恢复         | 查到了一行，且满足你写的那个表达式     | **继续告警**     |

**默认选中哪一个，取决于数据源类型。** 被归为日志类的那些——Elasticsearch、OpenSearch、 VictoriaLogs、Loki、ClickHouse、Doris——默认是第一个，因为没查到错误日志通常就真的说明 问题过去了。其余类型默认是第二个，因为一个连不上的数据库不等于一个健康的数据库。

ClickHouse 和 Doris 在这里算日志类，哪怕你对它们写的是 SQL 规则也一样， 所以别想当然，去看一眼那个下拉。

### 不对称阈值[​](#不对称阈值 "不对称阈值的直接链接")

第三个选项要填一条恢复表达式，语法和触发条件一样。这是防抖动的标准做法， 而且它能做到留观时长做不到的事：把两个阈值拉开。

```
触发      $A.value > 90

恢复      $A.value < 80
```

在 80 到 90 之间，告警既不再次触发也不恢复——就保持原样，直到指标往一边站队为止。 恢复表达式写错时会被当成「恢复条件不满足」，界面上没有明显报错， 所以配完用[模拟触发](https://n9e.github.io/zh/docs/alerting/test-fire.md)验一下。

### 对「数据消失」告警[​](#对数据消失告警 "对「数据消失」告警的直接链接")

日志类和 SQL 类规则在告警条件那一步还有一个独立的**数据缺失**开关： 之前查到过的数据现在查不到了就告警，重新查到就恢复。它有自己的级别和自己的自动恢复时长。

Prometheus 类规则没有这个开关。单写一条规则来做——用 `up == 0`， Categraf 环境用 `target_up == 0`。

## 恢复通知与重复通知[​](#恢复通知与重复通知 "恢复通知与重复通知的直接链接")

第 4 步还有三个字段，决定事件产生之后会怎样：

| 字段                 | 默认 | 作用                                                           |
| -------------------- | ---- | -------------------------------------------------------------- |
| 启用恢复通知         | 开   | 恢复时到底发不发消息。关掉不会让事件不恢复，只是恢复得悄无声息 |
| 重复通知间隔（分钟） | 60   | 一直不恢复的告警隔多久再提醒一次。`0` 表示不重复               |
| 最大发送次数         | 0    | 一条事件总共最多发多少条通知。`0` 表示不限                     |

一个值得记住的坑：**把一条正在告警的规则停用，你就永远收不到那条恢复通知了**， 因为停用的规则不产生任何事件。想临时静音，用[屏蔽规则](https://n9e.github.io/zh/docs/events/mute-rules.md)。

## 怎么选一组值[​](#怎么选一组值 "怎么选一组值的直接链接")

三组经得起用的组合：

**某个东西挂了。** 执行频率 `@every 30s`，持续时长 `0`，留观时长 `0`。 你要立刻知道，也要立刻知道它好了。

**资源有压力。** 执行频率 `@every 60s`，持续时长 `180`，留观时长 `300`。 持续三分钟的压力值得发一条；平静五分钟再宣布结束。

**某个比率越线。** 执行频率 `@every 60s`，持续时长 `120`， 然后在支持的规则类型上用不对称的恢复条件，而不是留观时长。

数字的行为和你预期对不上时，答案在[判定执行记录](https://n9e.github.io/zh/docs/alerting/execution-records.md)里： 每个周期都记着条件有没有成立、事件停在了哪个阶段。

## 下一步[​](#下一步 "下一步的直接链接")

* 这些字段驱动的状态机：[判定、恢复与状态变化](https://n9e.github.io/zh/docs/concepts/evaluation.md)
* 它就是停不下来：[告警为什么反复触发或从不恢复？](https://n9e.github.io/zh/docs/troubleshooting/alert-flapping.md)
* 它就是不开始：[告警规则不触发](https://n9e.github.io/zh/docs/troubleshooting/alert-not-firing.md)
