# 告警的路由与分组

## 告警的标签

prometheus发给alertmanager的每一条告警信息都是带有标签的，而且alertmanager是通过标签来标识每一条告警信息。比如说，下面是alertmanager接收到的一系列告警信息

```
{alertname="NodeCPU",instance="peng01",job="node-exporter",serverity="high",...}  time, annotation
{alertname="NodeMemory",instance="peng01",job="node-exporter",serverity="high",...}  time, annotation
{alertname="NodeCPU",instance="peng02",job="node-exporter",serverity="high",...}  time, annotation 
{alertname="NodeMemory",instance="peng02",job="node-exporter",serverity="high",...}  time, annotation
...
```

## 路由

假设Prometheus同时监控了两个组件：数据库组件与缓存组件；我们希望：数据库组件的告警能够发送给数据库小组的相关人员，缓存组件的告警能发送给缓存小组的相关人员。

基于告警信息的标签与alertmanager的路由机制，我们可以达到上面的效果。

比如，我们定义如下的路由树：

```
route:
  receiver: admin-receiver
  routes:
  - receiver: database-receiver
    match: 
      component: database    
  - receiver: memcache-receiver
    macth: 
      componnet: memcache
```

那么，当alertmanager收到一条告警信息时，首先会发送给admin-receiver；然后根据标签的匹配规则，如果该告警带有标签`component:database`，那么还会发送给database-receiver。

当然，如果数据库的告警还要继续细分，比如mysql的告警还要发送给mysql-receiver，marriadb的告警发送给marriadb-receiver，那么可以路由树如下：

```
route:
  receiver: admin-receiver
  routes:
  - receiver: database-receiver
    match: 
      component: database
    routes:
    - receiver: mysql-receiver
      match:
        type: mysql
    - receiver: marriadb-receiver
      match:
        type: marriadb   
  - receiver: memcache-receiver
    macth: 
      componnet: memcache
```

## 分组

有时候我们会遇到这样的场景：一台主机挂了后，主机上所有的服务都会挂掉，此时alertmanager会连续接收到很多的告警；如果每条告警都发一个邮件出去给接收者，那么短时间内邮件的发送量会很大。

那么，有没有可能把多条告警信息，合并成一个邮件发送出去呢？

答案是可以的，这就是alertmanager的分组功能。假设我们有如下的配置

```
route:
  receiver: admin-receiver
  group_by: ["instance"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
```

### Group By

上面我们设置了`group_by ["instance"]`，那么，当AlertManager接收到如下告警时

```
{alertname="NodeCPU",instance="peng01",job="node-exporter",serverity="high",...}  time, annotation
```

便会创建一个Group：`{instance="peng01"}`，然后把该条告警加入到这个Group中。接着，如果再接收到一条告警`{alertname="NodeMemory",instance="peng01",job="node-exporter",serverity="high",...} time, annotation` ，也会加入到这个Group中 。

如果接收到另一个告警

```
{alertname="NodeCPU",instance="peng02",job="node-exporter",serverity="high",...}  time, annotation
```

那么便会创建Group `{instance="peng02"}`，然后把这条告警放在这个Group中。（**注意：只有当一个新的告警到达，且它不属于任何已经存在的分组时，才会创建新的分组**）

而如果接到了一个告警，它没有`instance=xxx`这个Label，那么就会创建一个Group `{}`，把这个告警加入到这个Group中。

> 未设置Group By

上面我们讨论了设置了Group By后，alertmanager如何对告警进行分组。如果我们没有设置Group By，或设置为`group_by: []`，那么alertmanager便不会对告警进行分组（也有可能是对每一个告警中的标签创建一个分组，比如说收到一个告警只有标签`instance="peng01"`，那就创建一个分组`{instance="peng01"}`，收到一个另一个告警有标签`instance="peng01"`和`alertname="NodeCPU"`，就创建一个分组`{instance="peng01",alertname="NodeCPU"}`）。

**需要验证**

### Group Wait

上面我们提到当设置了Group By后，alertManager会对告警进行分组。当一条告警到达时，如果它不属于任何一个已存在的分组，alertManager会创建一个新的分组，然后将该告警加入到这个分组中。此时，alertManager并不会立即把这个告警发给Receiver，而是会等待`group_wait`的时间，如果在这个时间里有属于这个分组的其它告警到达，那么在`group_wait`时间后，alertManager会把这一组告警一次性发给Receiver。

注意：是创建一个分组后，才会等待`group_wait`的时间，等待其他属于这个分组的告警加入。当一个分组里面的告警都已经被“解决”（Resolved）后，这些告警与分组都会删掉，如果再来一个告警，则会重新创建分组。

关于告警如何被“解决”，请阅读后面的《扩展阅读》

### Group Interval

上面提到一个新的Group创建后，要等待`group_wait`的时间才会发通知给Receiver。当发送了通知以后，它会等待`group_interval`的时间，在这段时间内到达该Group的告警，会在`group_interval`后，会作为一个通知发送给Receiver（这个通知中会包含该分组内所有的告警）。

假设`group_interval`为5分钟，某个分组最后一次发送通知的时间为T，当`[T, T+5m]`的时间内该分组没有告警到达，而`T+6m`时该分组内有一个告警到达，那么这个告警会立即被发送给Receiver，而不会等到`T+10m`才发送。然后把`T+6m`作为最后一次发送通知的时间。

### Repeat Interval

当alertManager为某个分组发送了一个通知后，如果该分组里面的告警依然存在（即没有被“解决”）且在`repeat_interval`的时间内没有接收到新的告警，那么在等待`repeat_interval`时间后，alertManager才会为该分组重新发送一个通知。

比如说，`repeat_interval`为4小时，T时刻alertManager为某个分组发送了最后一个通知，这个通知包含了多个告警。在`[T, T+4h]`的时间里，该分组没有接收到新的告警，那么在`T+4h`时alertmanager才会为该分组重新发送一个通知。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://pshizhsysu.gitbook.io/prometheus/ff08-san-ff09-prometheus-gao-jing-chu-li/gao-jing-de-lu-you-yu-fen-zu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
