夜莺短信告警教程
夜莺监控(Nightingale)已经内置支持了邮件、钉钉、飞书、企微等多种通知机制,但是没有内置支持电话、短信等方式,是因为邮件、钉钉、企微、飞书等方式是协议固定的,但是电话、短信的通知方式,各家不同,一个是短信通道供应商不同,一个是各家封装的电话、短信接口不同,所以夜莺没有内置支持。
不过好在夜莺支持通过自定义脚本的方式对接新的通知媒介,只要你会写脚本,就可以接入任何通知媒介,电话、短信自然也不在话下。本文会以短信通知为例,讲解个中原理和配置方式。
告警通知这块,不仅仅是把告警消息投递出去,还需要告警降噪、按规则分派、排班、认领、升级、和 IM 打通、统计分析等更多诉求,我们建议您使用 FlashDuty 来作为一站式告警 OnCall 响应平台,可以对接 Nightingale、Prometheus、Zabbix、各类云监控,把众多监控系统的告警集中到一个中心平台来处理,提升告警处理效率。当然,也省去了您编写脚本的麻烦。
1. 增加短信通知媒介
菜单位置:告警通知-通知设置-通知媒介
。点击下面的添加,增加一个新的通知媒介,名称就叫“短信”即可,标识就叫“sms”即可,如下图所示:
增加通知媒介之后,在告警规则的配置页面,就可以勾选“短信”这个通知媒介了,如下图所示:
2. 编写短信通知模板
每一种通知媒介,都有对应的通知模板,啥意思呢?告警事件原本的格式是一条大 JSON,显然没法直接发出去,通过邮件发的时候要把这个 JSON 中的重要字段提取出来拼成 HTML 格式的邮件,发钉钉的时候要把这个 JSON 中的重要字段提取出来拼成 markdown 格式的消息,发短信的时候也是一样,要把这个 JSON 中的重要字段提取出来拼成短信的格式。
短信一般是普通文本字符串,有长度限制,咱们尽量只放重要内容,比如告警标题、告警内容、告警级别、告警时间等等,不要放太多无关紧要的信息,因为短信费用是按字数算的。
菜单入口在:告警通知-通知模板
,创建一个短信模板,标识姑且也叫 sms,内容就是你想要发送的短信内容,比如:
这个内容是可以自定义的,遵从 go template 语法,你可以参考其他的模板学习具体的写法。
n9e 的进程在调用通知脚本的时候,会把告警事件作为变量传给各个通知模板,进而渲染出最终的通知内容,然后把渲染结果+事件详情传给脚本,脚本中就可以直接取用了,无需再去处理模板渲染逻辑。
3. 编写短信通知脚本
夜莺告警的时候,可以自动调用通知脚本,你就在通知脚本里写你的逻辑就可以了。脚本需要先启用,菜单入口:告警通知-通知设置-通知脚本
,如下图:
我这里设置为启用,超时时间 10s,然后贴了一段脚本内容,内容如下:
显然这是一段 Python 脚本,比较简单,入口是 main 函数,从 stdin 中读取内容,然后根据告警事件中的通知渠道,调用 Sender 类中对应的发送函数,比如 send_sms、send_voice 等等,这里只是打印了一下,实际上应该是调用短信供应商的接口,把短信发送出去。
我来详细解释一下:
payload = json.load(sys.stdin)
夜莺 n9e 进程会把告警事件 encode 成一个 json,通过 stdin 的方式传给脚本,脚本里自然就通过 sys.stdin 的方式接收,因为是 json 字符串,使用 json.load 解码成 payload 对象然后把 payload 的内容打印到
.payload
文件中,方便调试,方便我们了解夜莺进程到底发过来了个什么内容
下面我把我的环境里的 .payload
贴到下面,怎么找到 .payload
呢?去 n9e 二进制的同级目录下找,注意这是一个隐藏文件。
payload 是个大 json,里边有两个顶层字段,一个是 event,表示事件内容,一个是 tpls,表示渲染出来的多个模板结果
继续解释那个通知脚本,
for ch in payload.get('event').get('notify_channels')
是循环遍历 payload.event.notify_channels,这个字段表示用户在告警规则里勾选的通知媒介列表,是个数组,上例的话,用户只勾选了短信,所以这个数组里只有一个元素,是sms
然后下面的代码是拼接一个函数名称,最终的效果是,如果 notify_channels 里有 sms 和 voice 两个元素的话,就会以此调用 send_sms 和 send_voice 函数。当然了,上例中 notify_channels 里只有 sms,所以只会调用 send_sms 函数,调用 send_sms 函数的时候,会把整个 payload 作为参数传入
下面我们来具体看一下 send_sms 函数的实现
要发短信,显然需要两个东西,一个是要发给哪些手机号,即手机号列表,另一个是发送的内容。通过解析 notify_users_obj 可以拿到告警接收人的手机号列表,上例中没有演示如何拿到告警模板渲染之后的通知内容,稍后再说。上例中的代码拿到了手机号并打印到 stdout 了,我们直接做个测试,看看日志里能否看到相关的输出。
3. 测试告警
下面我们做个测试。
3.1 配置告警接收人的手机号
要发短信显然是需要手机号的,先把手机号配置好。假设我想把告警发给 root 账号,那就给 root 账号设置一下手机号:
每个人可以设置自己的手机号,入口在页面右上角,点击自己的头像,进入个人信息设置页面即可设置。
3.2 创建告警接收组
夜莺里的告警接收人是通过告警接收组来管理的,所以我们先创建一个告警接收组,然后把 root 加入进去。
之后,我们在告警规则里选择这个告警接收组作为告警接收人。上面的例子中,告警接收组(也叫团队)可以展示为列表形式,也可以展示为树形结构,是在 系统配置-站点设置
里配置的。
3.3 创建告警规则
创建一个告警规则,入口在:告警管理-告警规则-新增
:
一个公司可能有很多告警规则,为了方便管理,告警规则要归属某个业务组。选中左侧业务组,右侧点击新增即可创建告警规则。如果你看不到业务组列表,要么就是从来都没有创建过业务组,要么是这个区块隐藏了,注意那个收起的 icon,可以通过那个 icon 收起和展开。下面是我创建的告警规则:
我的版本是 7.7.1,首先设置一下告警规则的标题,然后设置一下该规则要生效的数据源,然后配置 promql、执行频率、持续时长,为了尽快触发,我把 promql 设置成了一个必然会触发的条件,把执行频率调小,把持续时长设置为 0。然后下面的通知媒介勾选了短信,并且选择了一个告警接收组。
3.4 触发告警查看日志
保存之后去查看夜莺的日志。我是 docker compose 部署的,直接使用 docker logs -f nightingale
查看夜莺容器的日志了。稍等片刻,就可以看到夜莺进程调用了脚本,并打印了相关日志:
你也可以 grep send,就能看到类似上面的两条日志了。第一条 no sender for channel: sms
表示 n9e 的 go 进程里没有内置 sms 这个通知渠道,所以打印了这么一行 DEBUG,可以忽略无关紧要。第二条日志显示,夜莺的 go 进程调用了 notify_scriptt 脚本(脚本的内容就是页面上填写的那个通知脚本的内容),这个脚本有个输出 output,output 的内容是:send_sms not implemented, phones: dict_keys(['18612185520'])
,显然这个消息就是刚刚脚本里 print 的内容,一切都符合预期。
4. 继续完善脚本
上面的流程走到现在,其实已经跑通流程了。告警了之后调用了脚本,脚本里调用了 send_sms 函数,send_sms 函数里拿到了手机号。接下来我们要做的是,继续完善 send_sms 函数,把短信模板渲染之后的内容拿到,然后调用短信发送接口发送短信。
获取短信内容其实比较简单,模仿上面获取 notify_channels 的方式:
所以最终的代码类似:
一般短信发送接口都是封装的 HTTP 接口,你可以使用 requests 库调用短信发送接口。这里可能会掉坑。就是你的系统环境里没有 requests 这个 module,你需要安装一下,可以使用 pip 安装:
然后就可以在脚本里使用 requests 了。requests 的使用方法可以参考官方文档:https://docs.python-requests.org/en/latest/
好了,整个流程讲到这里相信你已经可以搞定了。如果你搞定了,真切的恳求你写一篇博客分享一下。因为大家的背景站的角度不同,我们提供的文档和教程有些人可能看不懂,你写的博客可能会帮助到他们,感谢,咱们双赢 :)
评论