今天遇到开源社区咨询:夜莺里如何引用标签和注解变量?这个问题如果通读文档,其实也能找到答案,不过相关知识是散落在各处的,这里就集中说一下,方便大家查阅。
哪里可以引用标签和注解变量
主要有两个地方引用标签和注解变量:
告警规则
告警规则的备注、附加信息,可以引用标签变量。对于不同的告警规则生成的告警事件,如果想渲染成不同的事件内容,就可以在这里做一些配置。比如磁盘告警,只想在告警消息里展示 path
标签;比如证书过期的告警,只想在告警消息里展示 target
标签。
告警规则的标题当前版本也可以引用标签变量,不过极为不建议这么做,因为标题是用来做去重、归类的,如果标题里包含标签变量,可能会导致同一类告警无法归并。后面的版本也可能会下掉标题里引用标签变量的功能。
消息模板
不同的通知媒介会有不同的消息模板,比如钉钉机器人有 markdown 模板,邮件有 HTML 模板,短信有文本模板。消息模板里也可以引用标签、注解变量。
消息模板是一个相对全局的东西,建议不同的通知媒介分别只定义一个消息模板,所以消息模板不应该引入定制化的渲染逻辑,如果有一些定制化的渲染逻辑,通常应该在告警规则里做。
告警规则引用标签变量举例
通过一个例子说明,假设我要配置一个内存相关的告警规则:
mem_free > 0
这里的阈值是 0,所以肯定会触发告警,方便我们测试。预览一下数据:
这个查询条件只返回了一条数据(因为我这是使用 Docker compose 启动的测试环境,里边只有一个 Categraf 在跑)。预览的数据中可以看到,标签部分只有一个 ident
标签。
下面我在附加信息(Annotations)里引用这个标签变量,例子如下:
定义了两个附加信息,其中 Runbook 比较简单,写了一个 URL 地址,这个 URL 中引用了 {{ .TagsMap.ident }}
变量,就是提取的 ident
标签的值,也可以写成 {{ $labels.ident }}
,类似 Prometheus 的标签变量引用方式。$labels
相当与是 .TagsMap
的别名。
另一个附加信息就比较复杂了,MemAvailablePercent,是通过调用模板函数 query
做了一个二次查询,即 mem_free
告警时,顺便获取了一下 mem_available_percent
的值。真实生产环境里,机器会有多台,告警的机器只有部分,所以执行 query
的时候,需要加上 ident
标签的过滤条件,确保查询到的 mem_available_percent
是和告警的机器一致的。printf
部分,是在拼接一个 promql,promql 中引用了 .TagsMap.ident
变量。query
的查询结果塞到了 $memMetrics
变量中,$memMetrics
是一个数组,所以用 range
遍历了一下,把每个条目的 ident 和 value 打印了出来。具体可以参考 模板函数文档。
消息模板引用变量举例
夜莺已经内置了很多告警消息模板,可以参考内置模板做调整,以 Dingtalk 的模板举例:
#### {{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}}
- **告警事件标签**:
{{- range $key, $val := $event.TagsMap}}
{{- if ne $key "rulename" }}
- {{$key}}: {{$val}}
{{- end}}
{{- end}}
{{if $event.AnnotationsJSON}}
- **附加信息**:
{{- range $key, $val := $event.AnnotationsJSON}}
- {{$key}}: {{$val}}
{{- end}}
{{end}}
{{$domain := "http://127.0.0.1:17000" }}
[事件详情]({{$domain}}/alert-his-events/{{$event.Id}}) | [屏蔽1小时]({{$domain}}/alert-mutes/add?__event_id={{$event.Id}}){{if eq $event.Cate "prometheus"}} | [查看曲线]({{$domain}}/metric/explorer?__event_id={{$event.Id}}&mode=graph}}){{end}}
这个模板里引用了很多变量,大都是以 $event.
开头的变量,这些变量都是事件对象的属性。其中告警事件的标签,是通过 range
遍历 $event.TagsMap
来实现的,$event.TagsMap
是一个 map 对象,$key
是标签名,$val
是标签值。
{{- range $key, $val := $event.TagsMap}}
{{- if ne $key "rulename" }}
- {{$key}}: {{$val}}
{{- end}}
{{- end}}
告警事件的附加信息,是通过 range
遍历 $event.AnnotationsJSON
来实现的,$event.AnnotationsJSON
也是一个 map 对象,$key
是注解名,$val
是注解值。
{{if $event.AnnotationsJSON}}
- **附加信息**:
{{- range $key, $val := $event.AnnotationsJSON}}
- {{$key}}: {{$val}}
{{- end}}
{{end}}
上面的语法都是 go template 语法,如果还有疑问可以把上面的 Dingtalk 的模板交给 gpt 进行解析,然后把修改需求告诉 gpt,让 gpt 帮你改。