夜莺和自定义告警通知方式?
首先,夜莺已经内置了多种常见的告警通知方式,包括不限于以下:
- dingtalk
- wecom
- feishu
- feishucard
- telegram
如果上述这些通知方式还不能满足你的需求,那么可以添加自定义的告警通知媒介
,首先需要在页面菜单:系统设置
-通知设置
-通知媒介
中添加自定义的通知媒介,例如添加短信
,其标识设置为sms
,状态为不隐藏
。添加配置后再去告警规则配置页面就能够看到新增的媒介了。
其次,自定义通知媒介
是通过执行自定义脚本
来实现的,这个脚本需要在系统配置
-通知设置
-通知脚本
里设置。设置通知脚本状态为启用
,设置合理超时时间
,最重要的就是设置脚本的内容,有两种方式:
- 直接填写脚本内容:粘贴Python脚本内容即可
- 指定路径路径:填写脚本存放的路径
不过推荐填写脚本内容
的方式,直接在页面上粘贴脚本内容,因为存放路径方式在集群部署时相对麻烦一些,需要在每个n9e/n9e-alert所在机器上放置脚本文件。
脚本文件可以参考etc/script/notify.py
来改写。上例中,新增的告警媒介标识是sms,所以脚本文件里我们要自定义一个send_sms方法来发送对应的告警通知。
class Sender(object):
...
@classmethod
def send_sms(cls, payload):# 自定义短信通知媒介方法
users = payload.get('event').get("notify_users_obj") # 获取所有接收通知的用户
phones = {}
for u in users:# 遍历用户获取手机号
if u.get("phone"):
phones[u.get("phone")] = 1
if phones:
# 核心是改写这个逻辑,调用自己公司的短信发送接口
print("send_sms not implemented, phones: {}".format(phones.keys()))
def main():
# 获取标准输入的json数据
# 脚本要能发送告警消息,得先拿到告警事件详情,夜莺会把告警事件 encoding 成 json 字符串,通过 stdin 的方式传给脚本
payload = json.load(sys.stdin)
# 为了方便调试,可以把告警事件的内容写到文件里,这样我们就知道夜莺通过 stdin 传过来的 json 是什么样的
with open(".payload", 'w') as f:
f.write(json.dumps(payload, indent=4))
# json 包含两个属性,其中 tpls 属性就是通知内容,可以在通知模版(系统设置-通知模板)中自行修改
# event 属性包含了这条告警的完整信息,可以从 notify_channels 看到要发送的通知媒介,notify_users_obj 看到接收告警的所有用户信息等等
for ch in payload.get('event').get('notify_channels'): # 遍历告警设置的通知媒介名称
send_func_name = "send_{}".format(ch.strip()) # 拼接通知媒介在脚本中方法名
if not hasattr(Sender, send_func_name): # 查看 Sender 中是否存在对应方法
print("function: {} not found", send_func_name) # 没有方法名继续下一个
continue
send_func = getattr(Sender, send_func_name) # 存在匹配方法名称
send_func(payload) # 调用对应方法,发送告警通知,比如 send_sms send_dingtalk send_wechat 等等
if __name__ == "__main__":
if len(sys.argv) == 1:
main()
elif sys.argv[1] == "hello":
hello()
else:
print("I am confused")
夜莺内置了邮件、企微机器人、钉钉机器人、飞书机器人等通知方式,如果用户在告警规则配置中设置了这些通知方式,夜莺内置就会调用对应的通知方式完成消息推送,如果用户设置了自定义的通知方式,夜莺没有内置对应的通知方法,就会在日志中打印 ’no sender channel: xxx’,这个时候就需要用户在脚本里实现通知方法了。
夜莺的 etc/script/notify.py
脚本中,也有 send_email send_dingtalk send_wechat send_feishu 等方法,但都是空实现,写了 pass
,这是因为这些通知逻辑在夜莺的 go 代码中已经内置了,脚本中就不需要重复发送了。
夜莺调用通知脚本的时候,会把告警事件详情序列化为 json 传给脚本,通过 stdin 的方式。脚本从告警事件中可以拿到告警接收人的手机号、邮箱等联系方式,进而调用自己公司的通道接口来发送即可。发送的时候,具体要发送什么内容?理应是从告警事件中获取一些字段来拼接,比如告警标题、告警备注、告警级别等等,但有的时候我们希望发送的内容格式比较多样,此时就需要引入模板机制了,通过模板定义发送消息的内容格式会更为方便。
夜莺支持自定义通知模板,在 etc/template
下内置了一些模板文件,我们可以在这个目录下创建自己的模板文件,之后就可以在页面上(系统设置-通知模板)来做二次修改。模板文件的格式是 go template,具体语法可以参考 go template 的文档。
自定义通知脚本,涉及到二次开发,如果您不想自己开发,也可以使用夜莺专业版,我们可以帮您完成通知媒介的对接,当然,专业版还有更多功能,您可以查阅这个链接了解详情:夜莺专业版 。
本文介绍的内容,也提供了视频演示,可以扫码观看:
Q:夜莺调用自定义通知脚本的时候,具体传递了哪些内容和字段?
A:传递的字段,具体可以参考 AlertCurEvent 结构,这个结构的各个字段都可以在模版中引用,引用的方式遵从 go template 语法。比如,告警事件中一般会有多个标签,模板文件中这个写法 {{.TagsJSON}}
可以按照数组的方式展示所有的标签。
Q: 夜莺调用自定义通知脚本的时候,如何自定义展示标签?
A: 比如,对于Kubernetes体系的监控数据,有的时候标签会非常非常多,看起来很费劲,有些朋友就会想,我是否可以只展示部分标签呢?
答案当然是可以的。TagsJSON
是所有标签的数组形式,TagsMap
是所有标签的map形式,我们可以使用TagsMap
来方便的获取特定的标签值,比如我这里修改企微的模板文件,不展示所有的标签:
**级别状态**: {{if .IsRecovered}}<font color="info">S{{.Severity}} Recovered</font>{{else}}<font color="warning">S{{.Severity}} Triggered</font>{{end}}
**规则标题**: {{.RuleName}}{{if .RuleNote}}
**规则备注**: {{.RuleNote}}{{end}}
**监控指标**: {{$metric := index .TagsMap "__name__"}}{{if eq "disk_used_percent" $metric}}机器:{{index .TagsMap "ident"}} 分区:{{index .TagsMap "path"}}{{else}}{{.TagsJSON}}{{end}}
{{if .IsRecovered}}**恢复时间**:{{timeformat .LastEvalTime}}{{else}}**触发时间**: {{timeformat .TriggerTime}}
**触发时值**: {{.TriggerValue}}{{end}}
**发送时间**: {{timestamp}}
注意上面监控指标那一行,先从TagsMap中拿到 __name__
对应的标签值,就是 $metric
,然后判断 $metric
是否是磁盘利用率,如果是就只展示ident标签的内容和path标签的内容,如果不是,就还是按照老样子,把TagsJSON全部展示出来。
Q:如果要把告警发送到私有化部署的飞书
,支持吗,该如何配置?
A: 夜莺也支持私有化部署的飞书。配置方式和飞书类似,具体的步骤如下:
- 第一步:访问菜单
系统设置
-》通知设置
-》通知媒介
,在该设置页面中,找到feishu
这一行,将其设置为不隐藏
; - 第二步:访问右上角菜单,打开
个人信息
设置页,在该页面中,选择添加联系方式
,在联系方式
下拉列表中选择feishu_robot_token
,将其值设置为如下类似的地址:https://open.xxx.com/open-apis/bot/v2/hook/71cea89b-xxxx-yyyy-zzzz-ddddd
, 其中open.xxx.com
为私有化部署的飞书域名; - 第三步:设置完个人信息后,将自己添加到某个
团队
中,比如该团队为ops-team
; - 第四步:去到
告警管理
-》告警规则
页面中,配置一个告警策略
,在告警策略的通知配置
部分,勾选feishu
,并在告警接收组
中选择ops-team
,至此,就可以把产生的告警推送到你的飞书了;
Q:默认通知媒介中,feishu
和 feishucard
有什么区别?
A: feishu
是纯文本的展示方式,feishucard
支持多媒体方式的展示效果。