监控与告警
监控与告警位于 platform 路由域,面向服务运行态、历史趋势、WebSocket 连接、告警规则、告警事件与通知闭环。
服务监控
「服务监控」(/system/monitor)接口前缀为 /api/monitor,权限码为 system:monitor:view。
| 接口 | 说明 |
|---|---|
GET /api/monitor | 当前监控快照 |
GET /api/monitor/timeseries | 进程内最近 1 小时时序数据 |
GET /api/monitor/history?range=... | 持久化历史趋势,按时间范围分桶聚合 |
GET /api/monitor/ws | WebSocket 实时连接指标(含租户分布与跨进程扇出统计) |
GET /api/monitor/ws/trend | WebSocket 连接趋势(进程内最近 1 小时,10 秒/点) |
GET /api/monitor/ws/trend/history?range=... | WebSocket 连接趋势的持久化历史,按时间范围分桶聚合 |
GET /api/monitor/stream | SSE 实时推送监控指标 |
SSE 首帧推送完整 metrics、全量 series 和 ws 指标;后续采样 tick 推送 metrics:diff、series:point 与 ws。客户端按差量深合并,避免整页轮询。
页面顶部的更新方式与刷新按钮作用于当前标签页:实时指标支持 SSE(约 10 秒一次)、定时刷新和暂停;历史趋势默认每分钟重新查询,也可暂停自动更新,二者分别记忆偏好。进入历史趋势时断开实时订阅并停止实时轮询,返回实时指标时恢复其更新方式。SSE 模式下手动刷新通过重连获取完整首帧,避免 HTTP 快照与差量推送交错覆盖。
历史趋势显示本次查询成功时间与最新数据时段;数据时段是聚合桶的起点,并非精确采样时间。手动刷新未发现历史数据变化时提示“暂无新增采样”;查询失败保留已显示的同范围图表并提示重试。
system_metric_samples 存储基础设施指标采样点,采样任务默认每分钟落库。/history 支持 1h、6h、24h、7d、30d 范围,每个范围使用不同分桶粒度并返回均值与峰值。
WebSocket 连接监控
「WebSocket 连接」(/system/monitor/websocket,权限 system:monitor:view)聚合网关节点、连接明细、消息采样、断开记录与关系拓扑。
消息流默认展示「业务消息」,另有「异常」「心跳」「全部」视图。采集端分别保留最近 200 条非心跳消息、100 条 ping / pong 和 100 条异常,集群合并时也分别限额;异常可能同时存在于业务或心跳窗口,「全部」按节点与消息 ID 去重。异常包括本地解析 / 写出失败以及无效帧。采样不保存消息正文,三个窗口与心跳摘要均按用户可见范围裁剪。
「心跳」页签数量按 ping / pong 明细条数计算,打开后直接显示原始心跳明细;下方再按在线连接汇总累计收到的 ping、成功写出的 pong、失败次数和最近时间。连接断开后摘要移除。连接详情的「最近业务消息」不受心跳覆盖。暂停会冻结当前快照与派生在线时长,手动刷新可更新冻结快照,恢复时重新建立速率基线。
入站「已解析」表示帧通过限速与协议解析;出站「已写出」表示本节点向打开的 socket 写出未抛错,两者都不代表业务处理完成或客户端确认收到。业务采样成功率和 Topic 统计仅使用非心跳窗口;累计收发、收发速率与保活仍包含全部帧。趋势中的失败值是独立异常窗口内的失败条数(历史分桶取峰值),不是每个采样周期新增失败数。
趋势口径分两段:/ws/trend 读 api 进程的采样环形缓冲(10 秒/点、保留 1 小时,随系统指标采样同节拍采集,进程重启后重新累积);/ws/trend/history 读每分钟落库的 ws_metric_samples,支持 1h、6h、24h、7d、30d 分桶。瞬时列(连接 / 在线用户 / 空闲)在两处都取窗口末值,增量列(新建 / 断开 / 收发)实时侧是相邻帧差分、历史侧是桶内求和,因此换算速率的窗口宽度不同:实时用 intervalSec、历史用 bucketSec。进程重启导致计数器回退时该帧直接丢弃(不写负值),趋势上表现为断点而非尖峰。ws_metric_samples 由数据保留策略按 30 天清理。
API / Worker 分离部署时,纯 Worker 订阅 API 节点的 wsStats 镜像并采样,承担历史落库; 它不广播自己的连接快照,不作为 API 节点展示。没有有效 API 镜像或 Redis 订阅降级时跳过采样,避免把未知状态写成零。 落库以数据库中的最新 sampled_at 为共享边界,事务锁串行化并发写入,Worker 轮换也不会重复消费之前的窗口; 失败写入不推进窗口,下一次可以重试。all 模式复用 API 的采样与订阅。
跨进程扇出统计:/api/monitor/ws 的 fanout 是平台级口径(不随可见范围裁剪),按节点给出订阅状态与 publish / publishFailed / delivered / dropped 计数,页面顶部汇总一条、节点表逐节点展示。推送为 at-most-once,订阅降级期间发出的信封不补发,因此 degradedNodes > 0、publishFailed 与 dropped 是“跨节点丢消息”唯一可观测的证据;计数为进程级累计值,该节点重启后归零(与累计收发同样会回退)。
租户维度:连接的 tenantId 由用户现解析,tenants 按可见连接聚合(平台侧用户归入 tenantId 为空的一组),页面据此提供租户筛选标签与「租户」列。可见范围与「在线用户」页一致:平台管理员在平台视角看全部,切到租户视角或非平台管理员只看本租户,且看不到绑定平台超管角色用户的连接。
指标口径
| 分组 | 指标 | 口径 | 单位 |
|---|---|---|---|
| 基础设施 | CPU / 内存 / 磁盘 / Swap / 负载 / 进程 CPU / 堆内存 / 事件循环延迟 / QPS / HTTP 错误率 / 网络上下行 / 磁盘读写 | 宿主机与进程采样器即时值 | % · 字节/秒 · ms |
| 基础设施 | 日志 ERROR 频率 / 日志 WARN 频率 | 近 5 分钟应用日志对应级别平均每分钟条数 | 条/分钟 |
| 后台调度 | 后台 worker 进程数 / 后台作业积压 | 近 90 秒内有心跳的 worker 角色进程数;全部 pg-boss 队列中已到执行时间、等待领取的作业总数(不含延后执行) | 个 · 项 |
| 流程引擎 | 健康分 / 队列积压 / 死信数 / 失败率 / 卡死数 | 工作流引擎运维指标 | 分 · 项 · % |
| 支付 | 支付失败率 / 支付卡单数 / 对账差异待处理 / 支付事件积压 / 支付回调失败率 | 支付域告警指标源实时聚合 | % · 项 |
| 开放平台 | 开放 API 错误率 / 单应用最高错误率 / 应用 Webhook 失败率 / 自动停用订阅数 | 开放平台告警指标源实时聚合 | % · 项 |
MONITOR_METRIC_META 声明每个指标的 scope:global 指宿主机或平台级口径,tenant 指按规则所属租户过滤。评估器按规则涉及的租户集合分组取快照。
日志级别频率指标
日志 ERROR / WARN 频率在 logger 的 logMethod hook 写入点由 lib/log-metrics.ts 计数,不扫描日志文件。实现特性:
- 不依赖文件 I/O,不受日志轮转影响;
- 按 epoch 分钟分桶保留近 5 个桶,读写时惰性淘汰;
- 与 QPS、HTTP 错误率一样是进程内口径,多实例部署时各实例统计自身;
- 计数失败不影响日志写入。
内置规则包括 ERROR ≥ 10 条/分持续 3 分钟(严重)和 WARN ≥ 30 条/分持续 5 分钟(警告)。此类告警事件操作列提供「查看日志」(需 system:log:files),跳转到 /system/log-files?file=app.YYYY-MM-DD.1.log&level=error。
链路追踪的应用日志面板按 traceId 在整个文件内精确匹配 JSON 日志顶层 reqId,保留最后 N 条匹配记录;URL 或正文包含目标 ID 的查询请求不会被当作该链路日志。面板优先打开链路节点日期对应的日志,支持切换 app、app-api、app-worker 日志及 gzip 归档。
面板中的「在日志文件中查看」跳转到 /system/log-files?file=xxx.log&traceId=目标链路ID。日志文件页使用 locateTraceId 读取首条精确匹配记录周围最多 N 条连续非空日志,命中前保留约半个窗口,再用后续记录补满;找不到时返回普通末尾 N 行。页面保留其他日志行,并像搜索一样自动定位、高亮对应链路,便于查看前后发生的其他请求。
告警中心
告警中心使用独立顶级菜单,不归属于「系统运维」目录。接口前缀为 /api/monitor-alerts,告警引擎由定时任务(evaluateMonitorAlerts,运行在 worker 角色)评估启用规则。规则达阈触发,指标恢复后自动解除;支持持续 N 分钟超阈、静默期、邮件 / Webhook / 站内信三渠道派发。
「后台 worker 进程数」这一指标是例外:worker 全部下线时评估器本身已停,因此 api 进程每分钟自查 worker 心跳,仅在为 0 时以该指标子集调用同一个评估器(lib/worker-watchdog.ts),规则、收件人、静默期与事件落库与其他告警一致;worker 恢复后由其自身的评估把规则置回 ok 并发恢复通知。种子规则「后台 worker 进程缺失」(< 1,持续 2 分钟)与「后台作业持续积压」(≥ 200,持续 5 分钟)默认启用。
规则的“告警状态”表示当前是否已触发:ok 在页面显示“未触发”,firing 显示“告警中”;“启用状态”独立控制规则是否参与评估。停用规则会关闭该规则尚未恢复的告警事件,并清除触发态与持续超阈计时。
| 页面 | 路径 | 权限 |
|---|---|---|
| 告警概览 | /alerts/overview | alert:overview:list |
| 告警规则 | /alerts/rules | alert:rule:list、alert:rule:create、alert:rule:update、alert:rule:delete、alert:rule:test |
| 告警事件 | /alerts/events | alert:event:list、alert:event:handle、alert:event:export |
通知与处理闭环
接收目标拆为 recipientUserIds 与 recipientEmails。系统用户通过稳定用户 ID 投递站内信;邮件渠道在派发时读取用户当前邮箱;recipientEmails 保存群组邮箱或外部联系人地址,并与用户邮箱去重。
dispatchAlertChannels 将真实投递结果回写到事件行的 notify_status / notify_channels / notify_error / notified_at。通知状态包括:
| 状态 | 含义 |
|---|---|
skipped | 规则没有配置任何可派发渠道 |
success | 所有已配置渠道均投递成功 |
partial | 部分渠道失败 |
failed | 全部渠道失败 |
事件的 handle_status(pending / acknowledged / closed)与系统判定的 status(firing / resolved)相互独立。认领会写入处理人和确认时间;标记已处理置为 closed;撤销认领置回 pending 并清空处理备注与确认时间。acknowledged_at 只在首次响应时写入。
筛选、批量与试发
规则列表支持按名称关键词、指标、级别、启用状态与告警状态筛选,事件列表支持关键词、指标、级别、告警状态、通知状态、处理状态、规则 ID 与触发时间范围筛选。规则支持批量删除与批量启停;事件支持单条与批量处理。告警规则的「查看事件」跳转到 /alerts/events?ruleId=N。
POST /api/monitor-alerts/{id}/test(权限 alert:rule:test)按规则当前渠道与接收人发送测试消息,返回派发结果;该操作不写事件表、不改规则运行态与 last_triggered_at。
SEED_MONITOR_ALERT_RULES 预置基础设施容量、日志异常频率、支付、开放平台与流程引擎关键失效信号,默认走站内信发给管理员用户 ID 1。