个人服务器的手机告警:怎么让它有用又不吵

个人服务器的手机告警:怎么让它有用又不吵 — 封面

我的个人服务器上跑着一个博客、一个工作台和一条每天早上自动发文章的流水线。之前它们出问题,我都是自己打开网页才发现。于是给服务器加了一个小小的 watcher,有事推送到手机上。

推送本身很容易,难的是让它不吵。一个隔三差五误报、半夜响、同一件事推十遍的告警,用不了几天就会被静音,等于没有。这篇整理我在设计时定下的几条规则。

一、只推“需要我做点什么”的事

watcher 每 60 秒检查一次,但只有下面几类情况会推送:

情况触发条件
站点或订阅源打不开连续 2 次检查失败;恢复时再通知一次
磁盘快满使用率 ≥ 85%
每日文章没发出来到 10:30 当天还没有
某台电脑很久没同步超过设定时长没有数据进来
工作台有新建议只推新产生的,汇总成一条

判断标准是:收到这条推送,我是不是需要去做点什么。CPU 偶尔冲高、某次请求慢了一点,这些我知道了也不会做什么,就不推。

二、连续失败才报,恢复也要报

网络偶尔抖一下,一次检查失败很正常。要求连续两次失败才推送,能挡掉绝大多数误报,代价是最多晚一分钟知道。

恢复通知同样重要。收到“站点打不开”之后,如果之后再没有消息,我不知道它是已经好了还是一直坏着,只能自己去看。有了“已恢复”,一来一回两条消息就把事情说清楚了。

三、同一件事只推一次

每 60 秒检查一次,如果磁盘一直在 86%,不做处理就会每分钟推一条。我的做法是给每条通知一个去重键,推过的键记进数据库,下次遇到同一个键就跳过:

def notify_once(key, title, body, level="warn"):
    if kv_get(f"notified:{key}"):
        return False
    if send(title, body, level):
        kv_set(f"notified:{key}", now_iso())
    return True

# 键的粒度决定“多久可以再提醒一次”
notify_once(f"disk:{today}", "磁盘使用率 86%", "...")       # 每天最多一次
notify_once(f"daily-missing:{today}", "今日文章未发布", "...")
notify_once(f"down:site:{incident_id}", "站点无法访问", "...")  # 每次故障一次

键里放什么,决定了重复提醒的节奏:放日期就是每天最多一次,放故障编号就是每次故障一次。

还有一个容易忽略的点:第一次启动时不要推旧积压。如果 watcher 一上线就把工作台里已有的建议全推一遍,第一印象就是“这东西好吵”。所以新建议只推 watcher 启动之后产生的,而且多条合成一条。

四、晚上安静,除非真的严重

23 点到第二天 7 点是免打扰时段,这段时间只推严重级别(比如站点整个打不开),其余的等到早上再说。时段写在配置里,跨午夜的写法要注意:“23-7”的意思是 23 点之后或 7 点之前,判断条件是“或”,不是“且”。

五、推送失败不能拖垮监控

推送要走外部服务,外部服务会超时、会限流、会改接口。如果发送函数抛异常,整个 watcher 循环就停了,监控反而因为推送出错而失效。所以 send() 的约定是永远不抛异常:每个渠道单独 try,设短超时,失败只记日志,返回是否至少有一个渠道成功。

def send(title, body, level="warn") -> bool:
    ok = False
    for name, fn in CHANNELS:            # 配置了哪些渠道就有哪些
        try:
            fn(title, body, level, timeout=8)
            ok = True
        except Exception as e:           # 一个渠道失败不影响其他渠道
            log.warning("notify %s failed: %s", name, e)
    return ok

只有发送成功时才写去重键,这样这次没发出去,下一轮还会再试。

六、渠道:选一个手机上本来就在用的

  • Bark:iPhone 上最省事,装好 App 拿到一个地址,填进配置就能用。
  • 企业微信、飞书、钉钉群机器人:适合本来就天天开着这些软件的人。飞书和钉钉建议打开“加签”,密钥和地址分开存放。

地址和密钥都只写在服务器的环境文件里,不进代码仓库。工作台上留了一个“测试推送”按钮,配完渠道点一下,比等一次真故障来验证靠谱得多。

小结

个人服务器的告警,目标不是“什么都知道”,而是“该知道的时候一定知道,其他时候别打扰我”。连续失败才报、恢复也报、同一件事只推一次、晚上只推严重的、推送失败不影响监控,这五条做到了,手机上的提醒才会一直被认真看。


上一篇
下一篇