夜莺监控(Nightingale)已经内置支持了邮件、钉钉、飞书、企微等多种通知机制,但是没有内置支持电话、短信等方式,是因为邮件、钉钉、企微、飞书等方式是协议固定的,但是电话、短信的通知方式,各家不同,一个是短信通道供应商不同,一个是各家封装的电话、短信接口不同,所以夜莺没有内置支持。
不过好在夜莺支持通过自定义脚本的方式对接新的通知媒介,只要你会写脚本,就可以接入任何通知媒介,电话、短信自然也不在话下。本文会以短信通知为例,讲解个中原理和配置方式。
告警通知这块,不仅仅是把告警消息投递出去,还需要告警降噪、按规则分派、排班、认领、升级、和 IM 打通、统计分析等更多诉求,我们建议您使用 FlashDuty 来作为一站式告警 OnCall 响应平台,可以对接 Nightingale、Prometheus、Zabbix、各类云监控,把众多监控系统的告警集中到一个中心平台来处理,提升告警处理效率。当然,也省去了您编写脚本的麻烦。
1. 增加短信通知媒介
菜单位置:告警通知-通知设置-通知媒介。点击下面的添加,增加一个新的通知媒介,名称就叫“短信”即可,标识就叫“sms”即可,如下图所示:

增加通知媒介之后,在告警规则的配置页面,就可以勾选“短信”这个通知媒介了,如下图所示:

2. 编写短信通知模板
每一种通知媒介,都有对应的通知模板,啥意思呢?告警事件原本的格式是一条大 JSON,显然没法直接发出去,通过邮件发的时候要把这个 JSON 中的重要字段提取出来拼成 HTML 格式的邮件,发钉钉的时候要把这个 JSON 中的重要字段提取出来拼成 markdown 格式的消息,发短信的时候也是一样,要把这个 JSON 中的重要字段提取出来拼成短信的格式。
短信一般是普通文本字符串,有长度限制,咱们尽量只放重要内容,比如告警标题、告警内容、告警级别、告警时间等等,不要放太多无关紧要的信息,因为短信费用是按字数算的。

菜单入口在:告警通知-通知模板,创建一个短信模板,标识姑且也叫 sms,内容就是你想要发送的短信内容,比如:
**级别状态**: {
{if .IsRecovered}}S{
{.Severity}} Recovered{
{else}}S{
{.Severity}} Triggered{
{end}}
**规则标题**: {
{.RuleName}}
**监控指标**: {
{.TagsJSON}}
{
{- if not .IsRecovered}}
**触发时值**: {
{.TriggerValue}}
{
{- end}}
**发送时间**: {
{timestamp}}
这个内容是可以自定义的,遵从 go template 语法,你可以参考其他的模板学习具体的写法。
n9e 的进程在调用通知脚本的时候,会把告警事件作为变量传给各个通知模板,进而渲染出最终的通知内容,然后把渲染结果+事件详情传给脚本,脚本中就可以直接取用了,无需再去处理模板渲染逻辑。
3. 编写短信通知脚本
夜莺告警的时候,可以自动调用通知脚本,你就在通知脚本里写你的逻辑就可以了。脚本需要先启用,菜单入口:告警通知-通知设置-通知脚本,如下图:

我这里设置为启用,超时时间 10s,然后贴了一段脚本内容,内容如下:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import sys
import json
class Sender(object):
@classmethod
def send_email(cls, payload):
# already done in go code
pass
@classmethod
def send_wecom(cls, payload):
# already done in go code
pass
@classmethod
def send_dingtalk(cls, payload):
# already done in go code
pass
@classmethod
def send_feishu(cls, payload):
# already done in go code
pass
@classmethod
def send_mm(cls, payload):
# already done in go code
pass
@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()))
@classmethod
def send_voice(cls, payload):
users = payload.get('event').get("notify_users_obj")
phones = {
}
for u in users:

最低0.47元/天 解锁文章
2314

被折叠的 条评论
为什么被折叠?



