值班排班(On-call):现状调研与路线建议
结论先行:上游 Keep 完全没有值班排班能力(无数据模型、无界面、无升级策略),这是更夫与 FlashDuty 的核心差距项,也是国内用户从"告警通知"走向"告警响应"的必经一步。 建议以「轻量排班 + 工作流动态解析」切入,不追求一步到位的完整 On-call 平台。
一、现状盘点
更夫(含上游 Keep)现有能力:
- 通知渠道:钉钉(@手机号)、企业微信(@手机号)、飞书(@所有人/按邮箱)——均已就绪
- 排班能力:无。没有班次模型、没有值班人解析、没有升级策略
- 相关仅有:
grafana_oncallprovider(对接外部 Grafana OnCall 系统,非自身能力)
FlashDuty / 睿象云对标能力(商业产品验证过的需求集):
- 排班表:日/周轮换、自定义周期、多组轮转、时区
- 升级策略(Escalation):超时未响应逐级通知备份值班人
- 响应确认(Ack):通知带确认入口,谁响应了有记录
- 值班表 × 告警路由:按班次自动路由"通知谁"
- 调班与假期
二、路线建议(三阶段)
P1:轻量排班 + 工作流动态解析(建议先做)
设计原则:不做完整 On-call 平台,先解决"通知该发给谁"这一个最高频问题。
- 新增数据模型:
schedule(值班组)+schedule_rotation(轮换规则:日/周轮换、成员列表、时区) - 工作流内新增解析函数:
{{ oncall.resolve("支付值班") }}→ 返回当前值班人的手机号/邮箱 - 三件套 provider 无需改动,工作流里直接消费:
yaml
actions:
- name: notify-dingtalk
provider:
type: dingtalk
with:
at_mobiles: "{{ oncall.mobiles('支付值班') }}"- 管理入口:设置页新增「值班管理」Tab(本期纯表单,不做日历可视化)
为什么这样切入:值班表的本质是"把一组人按时间规则解析成一个收件人列表", 我们的 provider 通知参数已经全部就位,只缺这一层解析。工作量可控(模型 + 解析器 + 表单), 价值直接(告别手工维护值班手机号)。
P2:Ack 确认与升级策略(已落地,设计借鉴 FlashDuty)
参照 FlashDuty 升级规则 吸收的设计:
- 升级触发双条件:「未关闭」/「未关闭且未认领」——采用后者为默认(有人认领即不升级)
- MTTA 度量:认领记录天然携带 created_at/acked_at,可算"从触发到有人接手"的时长(P3 统计消费)
- IM 内完成认领:通知消息附认领链接,值班人手机点开即认领(免登录,token 即凭证)
落地形态(引擎零改动,纯函数 + 记录 + 模板编排):
ackrecord记录:通知发出前经keep.oncall_ack_link(值班组, 告警名)创建,返回认领链接- 免登录认领页
/ack/{token}:手机浏览器点开一键认领 - 升级检查:
keep.oncall_claimed(值班组, 分钟数)供 interval 工作流判断超时未认领 → @ 全组 - 内置模板:更夫 · 值班告警钉钉通知(含认领)+ 更夫 · 值班升级钉钉通知
后续增强:认领页直接转派他人、多级升级策略(一线→二线→主管)、重复通知间隔配置
P3:值班可视化与调班
- 排班日历视图、假期/调班、多班组轮转叠加
- 与告警路由策略(Alert Routing)联动,按班次自动路由不同通知渠道
三、竞品参照
- FlashDuty(快猫星云):排班/Escalation 是其两大核心卖点,SaaS 定价按席位——证明该能力独立付费成立
- Grafana OnCall:开源但依赖 Grafana 生态,国内使用门槛高——可参考其轮换规则模型
- PagerDuty:Escalation Policy 是经典设计(一级超时 N 分钟 → 二级),语义可借鉴
四、不建议做的
- 不做完整 On-call SaaS(IM 集成、工单、通话语音外呼)——语音外呼在国内涉及号码资质,且远离更夫核心
- 不做与 Grafana OnCall 的深度双向集成——更夫自建轻量排班后,该 provider 保留给存量用户即可