OneUptime 状态页订阅者与通知机制:五种订阅通道、双重确认与公告计划的全景解析
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
本文围绕 OneUptime 状态页的订阅者体系与通知体系展开:状态页支持的五种订阅通道及其开启条件、访客订阅页的表单构成、邮箱双重确认(double opt-in)与退订流程、订阅者可自定义的资源与事件类型范围、通知模板定制,以及公告(Announcement)的创建向导、时间窗口计划规则与 SSRF 安全防护。读完后,你可以完整配置一个可运营的状态页订阅与通知方案,并能从数据模型层面理解每个开关字段的实际作用。
状态页订阅者与公告:两条互补的信息通道
状态页是用户主动来访问的页面,而订阅者是希望"不用来也能收到"的那批人——他们一次性留下邮箱、电话、Slack Webhook 或 HTTP 端点,之后状态更新会主动推送给他们。
公告是另一半任务。监控可以告诉访客"checkout 正在返回 500 错误",但监控无法告诉他们"周六要迁移数据库""某个第三方供应商今天状态不佳",或者"他们昨天看的那起事件已经彻底关闭了"。公告是覆盖这些检查项无法感知之事的自由文本通道,且发布到同一份订阅者列表上。本文同时覆盖这两个主题:五种订阅通道、访客如何订阅、订阅者可以自选哪些内容、双重确认与退订的完整流程,以及公告的撰写、计划与模板化保存。
五种订阅通道与开启条件
一个状态页支持五种订阅通道,每种通道在状态页中都有自己独立的配置项。进入状态页 → 你的页面 → 订阅者 → 订阅设置,可以看到五个开关:
| 通道 | 字段名 | 默认状态 |
|---|---|---|
| 邮箱订阅者 | enableEmailSubscribers | 开启 |
| SMS 订阅者 | enableSmsSubscribers | 关闭 |
| Slack 订阅者 | enableSlackSubscribers | 关闭 |
| Microsoft Teams 订阅者 | enableMicrosoftTeamsSubscribers | 关闭 |
| Webhook 订阅者 | enableWebhookSubscribers | 关闭 |
从源码结构看,这些字段定义在状态页数据模型 StatusPage.ts 上,并在 StatusPageService.ts 等服务层被消费,与文档描述的"邮箱默认开、其余默认关"一致。仓库中还存在一条专门删除早期"总开关"列enableSubscribers的数据库迁移 RemoveDeprecatedEnableSubscribersFromStatusPage:迁移注释说明该旧字段早已被"显示订阅页 + 按通道开关"的方案取代(superseded byshowSubscriberPageOnStatusPage+ the per-channelenableEmailSubscribers/enableSmsSubscribers/enableSlackSubscribersflags),这也印证了当前多通道开关的设计是最终形态。
每个通道还会在状态页的侧边菜单"订阅者"下拥有独立的列表页:邮箱订阅者、SMS 订阅者、Slack 订阅者、MS Teams 订阅者和Webhook 订阅者。你可以在这些列表中查看谁已注册、手动添加订阅者,或在某个订阅者条目上留下internalNote(内部备注)。
仅开启一个开关是不够的。状态页导航栏中的"订阅"入口,只有在显示订阅页面(showSubscriberPageOnStatusPage)打开、并且至少一个通道被启用时才会出现。如果你开启了邮箱订阅但关闭了"显示订阅页面",访客将没有任何路径到达订阅表单。
同样的五个开关还会出现在高级设置页的"订阅设置"卡片中,与"显示订阅页面"并排展示——底层是相同的字段。建议固定在专用的"订阅设置"页操作,因为订阅配置的其他部分都集中在那里。
访客在订阅页上看到什么
订阅页(Abonner)有一个子菜单,每个已启用的通道对应一个标签页——邮箱、SMS、Slack、MS Teams、Webhooks,分别对应路由/subscribe/email、/subscribe/sms、/subscribe/slack、/subscribe/microsoft-teams和/subscribe/webhooks。每个标签页只索要它需要的信息:
- 邮箱——标题"通过邮箱订阅",一个字段"你的邮箱",占位符为
abonnent@firma.dk。 - SMS——标题"通过 SMS 订阅",一个字段"你的电话号码",占位符为
+4512345678。 - Slack——标题"通过 Slack 订阅",包含Slack 工作区名称(用于校验)和Slack 入站 Webhook URL,占位符
https://hooks.slack.com/services/...。 - MS Teams——标题"通过 Microsoft Teams 订阅",包含Microsoft Teams 工作区名称和Microsoft Teams 入站 Webhook URL,占位符
https://outlook.office.com/webhook/...。 - Webhooks——标题"通过 Webhook 订阅",一个字段Webhook URL。每次状态页事件发生时都会向该地址发送 JSON
POST请求。
提交按钮叫"订阅",注册成功后页面显示"你已订阅"(Du er blevet tilmeldt.)。页面还分为新建订阅和管理已有订阅两个区域,已经订阅过的用户可以回到自己的设置而无需翻找旧邮件。
从数据模型看,这些表单字段一一对应订阅者实体 StatusPageSubscriber.ts 中的列:subscriberEmail(邮箱)、subscriberPhone(电话)、subscriberWebhook(Webhook)、slackIncomingWebhookUrl+slackWorkspaceName(Slack)、microsoftTeamsIncomingWebhookUrl+microsoftTeamsWorkspaceName(Teams)。其中 Slack 与 Teams 的 Webhook URL 列被标记为仅创建可见、不可读取(read: []),从访问控制配置看,这是一项防止公开页泄露入站 Webhook 地址的安全设计。
允许订阅者自选资源与事件类型
默认情况下,订阅者收到页面上的全部内容。"高级订阅者设置"卡片中的两个开关会改变这一点:
- 允许订阅者选择资源(
allowSubscribersToChooseResources)——默认关闭。开启后,订阅表单会出现"订阅所有资源"复选框;取消勾选后显示"选择要订阅的资源",让访客只挑选部分资源。 - 允许订阅者选择事件类型(
allowSubscribersToChooseEventTypes)——默认关闭。同样的形式:一个"订阅所有事件类型"复选框,取消后显示"选择要订阅的事件类型"。
事件类型共三种:Incident(事件)、Announcement(公告)、Scheduled Event(计划事件)。这与源码枚举 StatusPageEventType.ts 完全一致:
enum StatusPageEventType { Incident = "Incident", Announcement = "Announcement", ScheduledEvent = "Scheduled Event", }选择结果最终落在订阅者记录上,对应 StatusPageSubscriber.ts 中的以下字段:
| 字段 | 默认值 | 含义 |
|---|---|---|
isSubscribedToAllResources | true | 是否订阅全部资源 |
isSubscribedToAllEventTypes | true | 是否订阅全部事件类型 |
statusPageResources(Subscribed to Resources) | — | 多对多关联到具体的状态页资源 |
statusPageEventTypes(Subscribed to Event Types) | [] | 订阅的事件类型列表(JSON 列) |
适用场景:一个覆盖多个产品的页面。只使用你 API 的客户端并不想收到营销站点抖动时的每一条消息——与其让他们干脆退订,不如让他们自己裁剪订阅范围。
同一张卡片里还包含订阅者时区设置。
邮箱双重确认(Double Opt-In)
邮箱订阅者必须经过确认。当一个以邮箱地址创建的订阅者还不是已确认状态时,系统会将isSubscriptionConfirmed(是否已确认订阅)强制置为false,并生成一个六位数字的订阅确认令牌(Subscription Confirmation Token)。OneUptime 随后发送形如{statusPageUrl}/confirm-subscription/{statusPageSubscriberId}?verification-token={token}的确认链接。访客打开后进入"确认订阅"页面,成功后显示"订阅已确认"(Abonnement bekræftet)。
在数据模型中,这两个字段都有明确定义:isSubscriptionConfirmed 默认false,而 subscriptionConfirmationToken 为可空短文本列,且与确认标志一样被限制为不可通过读接口暴露。
SMS、Slack、Microsoft Teams 和 Webhook 订阅者跳过这一步——它们在创建时即把isSubscriptionConfirmed设为true。
未确认即静默。拉取通知收件人列表的查询会按isUnsubscribed: false且isSubscriptionConfirmed: true过滤。一个从未点击确认链接的邮箱地址会一直留在"邮箱订阅者"列表中,但收不到任何消息。如果有人坚称自己已订阅却什么都没收到,先检查这一列。
不存在关闭邮箱确认的开关——它对所有通过状态页注册的人无条件生效。而另一个独立的字段sendYouHaveSubscribedMessage(是否发送"你已订阅"消息,默认true,见 StatusPageSubscriber.ts)控制的是订阅者被确认之后发送的那封"你已订阅"通知邮件。
管理订阅与退订
每封发给订阅者的邮件都带有形如{statusPageUrl}/update-subscription/{statusPageSubscriberId}的退订链接。该页面名为"更新订阅",会告诉访客可以在此修改设置或取消订阅。页面包含:
- 当前允许的资源与事件类型选择器;
- 一个"退订"复选框,说明为"从所有资源退订",它写入
isUnsubscribed(已退订,默认false); - 一个名为"更新订阅"的按钮,保存成功后显示"你的更改已保存"。
如果访客弄丢了链接,可以在订阅页的管理已有订阅区域点击"发送管理链接"。OneUptime 会回复说明管理邮件已发出,如果没收到请检查垃圾邮件文件夹。
支撑这一切的后端端点为:POST .../subscribe/:statusPageId、POST .../manage-subscription/:statusPageId、POST .../get-subscription/:statusPageId/:subscriberId与PUT .../update-subscription/:statusPageId/:subscriberId。
退订是翻转一个标志而不是删除记录,因此该条目会一直保留在通道列表中并标记为"已退订"——将来需要解释"为什么某个地址不再收到消息"时,这条历史仍在。
订阅者会收到什么通知
订阅者会收到上述三种事件类型的通知,但每种来源都有独立的开关,避免误发。
公告通知
公告本身带有是否通知状态页订阅者(shouldStatusPageSubscribersBeNotified)字段,在创建表单中显示为"通知状态页订阅者"复选框,默认开启。如果公告在**受影响监控(可选)**中指定了监控,则通知范围限定为这些监控的订阅者;留空则通知所有订阅者。
计划维护事件
计划维护事件(Scheduled Maintenance)拥有自己的一组订阅者字段:是否在事件创建时通知状态页订阅者、是否在事件状态变为进行中时通知、是否在事件状态变为结束时通知,以及事件前的订阅者通知和下一次事件前通知时间两个提前量配置。事件上的状态页字段决定它出现在哪些页面上,而是否应在状态页显示决定它是否可见。
从源码结构看,通知事件粒度比三种业务事件类型更细:StatusPageSubscriberNotificationEventType.ts 枚举列出了事件创建、状态变更、备注创建、复盘发布等独立事件(如SubscriberIncidentCreated、SubscriberIncidentStateChanged、SubscriberScheduledMaintenanceStateChanged),还包括订阅生命周期事件(确认、订阅、管理)与周期性报表事件,供模板按事件类型分别配置文案。
事件(Incident)
Incident是第三种事件类型。一个事件凭什么会出现在状态页上——它涉及哪些资源、哪些状态会保持它可见——参见 OneUptime 文档中"事件状态与严重级别"一章。
状态页侧边菜单中的通知日志部分({id}/notification-logs)是排查"这个页面实际发送了什么"时的入口。
通知模板定制
"订阅设置"中的通知模板卡片展示该状态页当前使用的模板,列为模板名称、事件类型和通知方式——你可以按事件类型、按通道分别定制文案,而不是对所有消息使用同一套话术。
项目级模板位于上一层级:状态页 → 设置 → 订阅模板,与公告模板并列。
邮箱页脚、自定义 SMTP 与 Twilio
"订阅设置"上还有三张卡片控制订阅者消息如何离开你的项目:
- 邮箱页脚设置——"启用自定义邮箱页脚文本"和"订阅者邮件通知页脚文本",为订阅者邮件加上你自己的页脚;
- 自定义 SMTP——"自定义 SMTP 配置",让订阅者邮件走你自己的邮件服务器而非默认服务器;
- Twilio 配置——"Twilio 配置",SMS 订阅者使用的 Twilio 账号。
如果你有邮箱订阅者,值得尽早配置自定义 SMTP:来自自己域名的邮件被过滤的概率更低,深夜两点读到邮件的客户也更可能信任它。
公告(Announcement)的创建
公告是项目级别的一条记录(模型StatusPageAnnouncement),可以发布到一个或多个状态页,可选地限定到特定监控,并带有显示时间窗口。
创建入口在状态页 → 更多 → 公告,或在单个状态页侧边菜单的公告中。创建表单是一个四步向导:
- 基本信息——公告标题(必填,至少两个字符)、描述(Markdown,可选)、附件(与公告一起放在状态页上的文件);
- 状态页——在此状态页显示公告,必填的多选列表,一条公告可以同时命中多个页面;
- 受影响资源——受影响监控(可选),不选则所有订阅者都会收到通知;
- 时间与设置——开始显示公告的时间(必填,默认为现在)、停止显示公告的时间(可选)、通知状态页订阅者(默认开启)。
访客在/announcements阅读公告,页面分为当前公告与历史公告两个区域,每条都标注"发布于"时间戳。当前生效的公告同时悬挂在概览页顶部。如果没有任何内容可显示,页面会显示"没有公告"并注明尚未发布任何内容。
附件通过GET {statusPageCrudPath}/status-page-announcement/attachment/:statusPageId/:announcementId/:fileId提供,背后是与状态页本身相同的读取校验——私有页面上的附件保持私有。
公告计划(Plan)机制的底层规则
显示时间(showAnnouncementAt)与结束时间(endAnnouncementAt)控制一切,但概览页和公告列表回答的是两个不同的问题,这个差异容易让人踩坑:
- 概览页:当
showAnnouncementAt早于当前时间,且endAnnouncementAt晚于当前时间或为空时,公告显示出来; /announcements列表:只列出showAnnouncementAt落在显示公告历史(天数)(showAnnouncementHistoryInDays,默认 14 天)范围内的公告,然后在客户端按活跃/历史分组。
两个值得在排期时记住的推论:
- 没有结束时间的公告永不过期。如果"停止显示公告的时间"留空,它会永远挂在概览页上。所有有时限的内容都应设置结束时间。
- 旧但仍活跃的公告可能从列表中消失。如果公告的显示时间早于
showAnnouncementHistoryInDays天之前,它会从/announcements列表中消失,但仍保留在概览页上。长期运营公告时应调大这个历史窗口。
公告是否显示本身由高级设置中的公告设置卡片控制:显示公告(showAnnouncementsOnStatusPage,默认true)与显示公告历史(天数)(默认 14)。若"显示公告"关闭,公告端点会直接拒绝请求。
公告模板
如果反复发布同一类公告——每月的维护预告、某个第三方反复出现的服务降级——就提前做成模板。状态页 → 设置 → 公告模板承载模型StatusPageAnnouncementTemplate,其表单要求模板名称、模板描述、公告标题、描述、在此状态页显示公告、受影响监控(可选)和通知订阅者,让发布范围与"是否通知"这两个决定一次做出,而不是每次重新判断。
Webhook 订阅者与 SSRF 防护
Webhook 订阅者在每次状态页事件发生时收到一个 JSONPOST请求,因此把状态页更新导入你自己的系统(聊天机器人、内部仪表盘、工单系统)是最简单的方式。
由于订阅是公开页面上的公开操作,OneUptime 会对目标地址做防护:
- 普通Webhook URL在接受前会被校验:私有地址、回环地址、链路本地地址与云元数据地址都会被拒绝,无法把一个订阅指向 OneUptime 安装所在网络内部的地址;
- Slack 入站 Webhook URL必须以
https://hooks.slack.com/services/开头。
如果一个 Webhook 订阅在注册时被拒绝,内部地址或格式错误的 URL 是你应该首先排查的原因。
进一步阅读
- 状态页 – 概览——状态页是什么、如何组成;
- 状态页 – 资源与分组——订阅者可以从中挑选的监控与分组;
- 状态页 – 品牌与域名——自定义域名、Logo 以及邮件所链接页面的外观;
- 公共 API——以编程方式读取状态页数据。
配合数据模型源码 StatusPageSubscriber.ts 与事件类型枚举 StatusPageEventType.ts、StatusPageSubscriberNotificationEventType.ts,可以在字段级别核对本文所述的每个开关、默认值与访问控制配置。
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考