消息模板
夜莺 v9 消息模板:用 Go template 语法定义告警通知的标题和正文,平台内置 30+ 模板覆盖主流 IM/短信/Webhook 渠道,可基于事件字段做高度自定义。
概述
消息模板 = 通知发到 IM / 邮箱 / Webhook 时最终长什么样的定义。
侧栏路径:通知 → 消息模板,URL /notification-templates。
它和通知媒介的关系:
- 通知媒介 = 答 “怎么发” — 拿什么 SMTP/Webhook 把消息送出去;
- 消息模板 = 答 “发什么内容” — 标题、正文、HTML 样式、变量引用;
- 通知规则 = 答 “发给谁” + 选媒介 + 选模板。
平台内置了 30+ 套常见渠道的模板(覆盖钉钉、企业微信、飞书、Lark、Email、PagerDuty 等),多数场景直接用就行。需要个性化(公司 logo、企业话术、补充字段)时基于内置模板克隆一份再改。
页面布局
左右两栏:
- 左侧:模板列表 + 搜索框 + 新增按钮
- 每条显示:模板标识(如
Email/Dingtalk/Wecom)+ 可见性(公开 / 仅自己 / 指定团队)
- 每条显示:模板标识(如
- 右侧:选中模板的详情
- 头部:标识、媒介类型、编辑 / 复制 / 删除按钮;
- 中间:字段标识区域(如
content、subject、title)— 每个媒介需要哪些字段是它定的; - 编辑器:Go template 语法的 Markdown / HTML / Text 内容;
- 「AI 生成」按钮:用 LLM 直接生成模板片段(需先配 LLM 管理);
- 底部:保存、预览模板内容;
- 右下:可用字段速查文档(含
$event.*完整字段表)。
内置模板速览
按渠道分类的内置模板:
| 渠道类型 | 内置模板 |
|---|---|
| 企业 IM | Dingtalk、Wecom、Feishu、FeishuCard、Lark、LarkCard、Telegram、Discord、SlackBot、SlackWebhook、Mm、MattermostBot、MattermostWebhook |
| 邮件 / 短信 / 语音 | Email、Tencent SMS、Tencent Voice、Aliyun SMS、Aliyun Voice |
| 运维平台 | Callback、JSMAlert、Jira |
| 特色模板 | 北极星钉钉/飞书/企微消息、灭火图 钉钉/飞书/企微卡片 |
新装的环境就有这些,无需手工创建。直接在 通知规则 里挑选即可。
字段标识:模板 ↔ 媒介的对接契约
关键概念:消息模板里定义的字段名(如 subject、content、title),必须和通知媒介在 body 配置里引用的字段名一一对应。
举例:钉钉媒介在 body 里写:
{
"msgtype": "markdown",
"markdown": {
"title": "{{$tpl.title}}",
"text": "{{$tpl.content}}"
}
}
它引用了 $tpl.title 和 $tpl.content —— 所以钉钉对应的消息模板必须有 title 和 content 两个字段标识。否则发出去标题/内容会是空。
如果自己加新字段(比如想多加一段"建议处理"),记得两边都改 — 模板里加字段 + 媒介 body 里引用。
模板语法快速回顾
模板使用 Go template 语法,可以引用告警事件(AlertCurEvent)的所有字段。
最简模板示例
级别状态: S{{$event.Severity}} {{if $event.IsRecovered}}Recovered{{else}}Triggered{{end}}
规则名称: {{$event.RuleName}}{{if $event.RuleNote}}
规则备注: {{$event.RuleNote}}{{end}}
监控指标: {{$event.TagsJSON}}
{{if $event.IsRecovered}}恢复时间:{{timeformat $event.LastEvalTime}}{{else}}触发时间: {{timeformat $event.TriggerTime}}
触发时值: {{$event.TriggerValue}}{{end}}
发送时间: {{timestamp}}
{{$domain := "http://your-n9e-domain"}}
事件详情: {{$domain}}/alert-his-events/{{$event.Id}}
常用控制语法
| 用法 | 示例 |
|---|---|
| 条件判断 | {{if eq $event.Severity 1}}🚨 紧急{{else if eq $event.Severity 2}}⚠️ 警告{{else}}ℹ️ 信息{{end}} |
| 循环 | {{range $i, $tag := $event.TagsJSON}}- {{$tag}}{{"\n"}}{{end}} |
| 变量赋值 | {{$dashboard_url := printf "%s/alert-his-events/%d" $domain $event.Id}} |
| 函数调用 | {{timeformat $event.LastEvalTime}}、{{timestamp}} |
| 引用标签 | {{$event.TagsMap.instance}}、{{$event.TagsMap.service}} |
| 引用注解 | {{$event.AnnotationsJSON.summary}} |
常用事件字段
| 字段 | 含义 |
|---|---|
$event.RuleName |
告警规则名 |
$event.RuleNote |
规则备注 |
$event.Severity |
1/2/3 三级 |
$event.IsRecovered |
true = 恢复事件 |
$event.TagsJSON |
标签数组 |
$event.TagsMap.<key> |
单个标签值 |
$event.TriggerValue |
触发瞬时值 |
$event.TriggerTime |
触发时间戳 |
$event.LastEvalTime |
最近评估时间戳 |
$event.GroupName |
业务组名 |
$event.TargetIdent |
目标设备标识 |
$event.Cluster |
数据源名 |
$event.AnnotationsJSON.<key> |
注解值 |
完整字段表和模板函数列表见右下角的"可用字段说明"区域(页面内嵌的字段速查表)。模板函数实现见 ccfos/nightingale 的 tplx.go 和 模板函数介绍 文档。
实操:克隆 + 改造一个模板
不要直接改内置模板(升级会被覆盖)。推荐流程:
- 在左侧列表选要参考的模板,比如
Dingtalk; - 在右侧上方点「复制」按钮 — 自动新建一份
Dingtalk_copy副本; - 改副本:起个新标识(如
Dingtalk-ops表示运维专用版)、修改 content 内容; - 「预览模板内容」按钮:拿一条样例事件渲染看看效果;
- 满意后保存;
- 去 通知规则 把要用这套样式的规则切换到新模板。
AI 生成模板
「AI 生成」按钮调用平台 LLM 管理 配的默认大模型,用自然语言生成模板片段。典型 prompt 例子:
- “生成一个带 emoji、按级别分颜色的钉钉 markdown 告警模板”
- “生成一个简洁的邮件主题,要包含级别和规则名”
生成的内容会自动填入编辑器,可以再人工调整。前置条件是 LLM 管理里至少有一条启用 + 默认的 LLM 配置。
常见问题
Q1:保存模板后通知里没生效?
A:检查这 3 点:
- 缓存:模板缓存几秒,等 10-30 秒再触发告警;
- 正确选择:通知规则 里"消息模板"那一栏选的是不是新模板;
- 字段标识对:模板里的字段名(
content、subject等)必须和通知媒介 body 里引用的$tpl.xxx完全一致。
Q2:预览看着对,发出去全是 <no value>?
A:模板里用了事件没有的字段。比如 $event.TagsMap.dept,但实际事件标签里没 dept 这个 key。两种处理:
- 用条件判断:
{{if $event.TagsMap.dept}}{{$event.TagsMap.dept}}{{else}}未知{{end}}; - 或者直接保证标签必填(用标签词表注入默认值)。
Q3:想发企业微信/钉钉的图片或链接卡片,但内置模板里没找到?
A:
- 钉钉群机器人有"卡片消息"格式 — 用
Dingtalk模板,把content改成钉钉 ActionCard 格式即可; - 飞书/Lark 用
FeishuCard/LarkCard模板,它们已经是卡片样式; - 想发完全自定义的内容,用
Callback模板 + 通用回调媒介,自己拼 JSON 转发。