核心要点
- Prometheus 常用
summary和descriptionannotation 控制告警消息内容;夜莺也可以通过告警规则的自定义字段实现类似效果。 - 默认告警消息会展示大量标签,K8s 场景下尤其容易变得冗长,影响值班人员快速判断。
- 推荐做法是在告警规则里生成
summary字段,再在通知模板中优先渲染summary,减少对完整标签列表的依赖。 - 这篇文章以钉钉模板为例,展示如何引用
$event.AnnotationsJSON.summary,以及如何删掉默认的标签遍历片段。
缘起
Prometheus 告警规则中,通常会配置 summary 和 description 两个 annotation,即便告警事件有很多标签,也会通过自定义这俩 annotation 来实现告警信息的自定义,确保告警信息的简洁和可读性。当然,弊端就是每个 alerting rule 都需要配置这俩 annotation,导致配置文件冗长。
夜莺监控的告警规则则不需要配置 summary 和 description,省去了这俩字段的维度,但是夜莺监控的告警通知信息中,包含了所有的标签信息,导致告警信息冗长。夜莺的告警消息举例:

上例中,直接把指标名字、instance、job 等标签都展示了出来,比较冗长,如果是 K8s 类的告警,可能还会有更多的标签信息,比如 pod 名字、namespace 等等,就更冗长了。
如果你想在夜莺中实现类似 Prometheus 那样的消息自定义的效果,也有办法,本文介绍如何自定义夜莺监控的告警通知信息,达到简洁、可读的效果。
逻辑讲解
首先,这个自定义的消息内容,应该是告警规则颗粒度的,比如 CPU 的告警和 DISK 的告警,想要展示的标签信息是不一样的。所以,告警规则中应该支持配置。实际夜莺的告警规则中有个自定义字段的配置,就相当于 annotation,可以在里边定义 summary、description 等字段。之后生成的告警事件中,就有 summary、description 等字段了,然后最终在消息模板中引用这些字段即可。
实操讲解
告警规则中我们可以这么配置:

上例中,我自定义了一个 summary 字段,提取了标签中的 instance 和 job,其他告警规则也可以类似这么定义,然后再最终的消息模板中引用这个 summary 即可。以钉钉举例,我的钉钉消息模板如下:
#### {{if $event.IsRecovered}}<font color="#008800">💚{{$event.RuleName}}</font>{{else}}<font color="#FF0000">💔{{$event.RuleName}}</font>{{end}}
---
{{$time_duration := sub now.Unix $event.FirstTriggerTime }}{{if $event.IsRecovered}}{{$time_duration = sub $event.LastEvalTime $event.FirstTriggerTime }}{{end}}
- **告警级别**: {{$event.Severity}}级
{{- if $event.RuleNote}}
- **规则备注**: {{$event.RuleNote}}
{{- end}}
{{- if not $event.IsRecovered}}
- **当次触发时值**: {{$event.TriggerValue}}
- **当次触发时间**: {{timeformat $event.TriggerTime}}
- **告警持续时长**: {{humanizeDurationInterface $time_duration}}
{{- else}}
{{- if $event.AnnotationsJSON.recovery_value}}
- **恢复时值**: {{formatDecimal $event.AnnotationsJSON.recovery_value 4}}
{{- end}}
- **恢复时间**: {{timeformat $event.LastEvalTime}}
- **告警持续时长**: {{humanizeDurationInterface $time_duration}}
{{- end}}
{{- if $event.AnnotationsJSON.summary}}```
{{ $event.AnnotationsJSON.summary }}
```{{- end}}
{{$domain := "http://127.0.0.1:17000" }}
{{$mutelink := print $domain "/alert-mutes/add?busiGroup=" $event.GroupId "&cate=" $event.Cate "&datasource_ids=" $event.DatasourceId "&prod=" $event.RuleProd}}
{{- range $key, $value := $event.TagsMap}}
{{- $encodedValue := $value | urlquery }}
{{- $mutelink = print $mutelink "&tags=" $key "%3D" $encodedValue}}
{{- end}}
[事件详情]({{$domain}}/alert-his-events/{{$event.Id}}) | [屏蔽1小时]({{$mutelink}}) | [查看曲线]({{$domain}}/metric/explorer?data_source_id={{$event.DatasourceId}}&data_source_name=prometheus&mode=graph&prom_ql={{$event.PromQl|urlquery}})
上例中,最重要的部分是增加了:
{{- if $event.AnnotationsJSON.summary}}```
{{ $event.AnnotationsJSON.summary }}
```{{- end}}
先判断一下自定义字段中是否有 summary 字段,如果有就渲染,如果没有就不渲染。渲染的时候我给放到 code 块里了,这样可以稍微美观一点。另外删除之前消息模板里的这部分:
- **告警事件标签**:
{{- range $key, $val := $event.TagsMap}}
{{- if ne $key "rulename" }}
- {{$key}}: {{$val}}
{{- end}}
{{- end}}
最终效果如下:

FAQ
Q1:为什么不直接展示所有标签? A:所有标签对排障有价值,但不一定适合第一屏通知。值班人员收到消息时更需要先看到规则名、级别、触发值、持续时间和摘要,完整标签可以放到事件详情里查看。
Q2:summary 字段应该写什么?
A:建议写最能帮助判断影响范围的信息,比如 instance、job、namespace、pod 或业务自定义标签。不同告警规则关注点不同,summary 应该按规则配置。
Q3:没有配置 summary 会怎样?
A:模板里的判断逻辑会先检查 $event.AnnotationsJSON.summary 是否存在。没有这个字段时就不渲染该代码块,不会影响其它告警内容。
结论
干净的告警通知不是减少信息,而是把信息分层:通知里展示最关键的摘要,详情页保留完整标签和上下文。夜莺的自定义字段加消息模板,正好可以实现这层分离。
enjoy~