- process_heartbeat / process_heartbeat_sample (0034): api / worker / worker:agent / all
upsert every 15s (event loop lag last/max, concurrency, running runs, SSE connections, memory)
- GET /system/health (admin): processes with 45s stale flag, SSE, DB latency/size/connections,
disks (DATA_DIR / library roots / download dirs, cache thresholds), mount sentinel checks
with IO timeout, engine pending/oldest/24h failure rate, schedules
- GET /system/health/history?hours=: bucketed lag / running / SSE series
- /engine/runs and /engine/runs/{id}: business {kind, refId, title, triggeredBy} joined from
run input / task / agent_run / tasks_run_meta / outbox; businessKind / businessRefId filters
- docs/runbook/ops.md: field meanings and alert thresholds
Co-Authored-By: Claude Opus 5.5 <[email protected]>
5.6 KiB
5.6 KiB
进程与健康
控制台「运行日志 → 进程与健康」的数据来源。后端在 apps/server/src/modules/system/,两个端点都只给 admin。
心跳怎么写
| 进程 | 谁写 | process_kind |
|---|---|---|
--role api |
system 模块注册路由时起写入器 | api |
--role worker(io 组) |
worker/index.ts |
worker |
--role worker:agent |
worker/index.ts |
worker:agent |
--role all |
worker/index.ts(同进程的 API 不再单写) |
all |
- 每 15 秒 upsert
process_heartbeat一行,同时往process_heartbeat_sample追加一条采样。 - 行主键
instance_id = <kind>:<host>:<pid>,容器重启覆盖同一行。 - 写入方每小时裁剪一次:采样保留 7 天,7 天没心跳的进程行删除。
- 写库失败只记 debug 日志,不影响业务。
GET /system/health 字段
| 字段 | 含义 |
|---|---|
level |
各段最差档:ok / warn / critical。取不到数据的段是 unknown,不参与汇总 |
api |
处理本次请求的 API 进程:版本、启动时间、运行秒数 |
processes[] |
最近 24 小时有心跳的进程 |
processes[].stale |
超过 45 秒没心跳 |
processes[].eventLoopLagMs |
最近一次采样的事件循环延迟(1 秒采一次) |
processes[].eventLoopLagMaxMs |
最近一个心跳周期(15 秒)内的最大延迟 |
processes[].concurrency |
引擎 worker 并发 {io, agent};api 进程为 {} |
processes[].runningRuns |
本组任务正在执行的 run 数。同组多实例时是整组合计;api 进程为 null |
processes[].sseConnections |
本进程打开的 SSE 流数。不托管 HTTP 的进程为 null |
processes[].extra |
rssBytes、heapUsedBytes、lifetimeMaxLagMs,worker 另有 group、lagWarnings、probeMaxLagMs |
sse.connections |
存活 api/all 进程的 SSE 连接合计 |
db |
select 1 延迟、库大小、本库连接数(按 active / idle / idle in transaction 分)与 max_connections |
disks[] |
DATA_DIR、每个启用的库根、每个下载器路径映射的 statfs 用量 |
diskThresholds |
取自设置 cache.resumePercent(warn)和 cache.hardThresholdPercent(critical) |
mounts[] |
库根做哨兵检查(checkRoot),下载目录只查目录可读。status:online / offline / timeout |
engine |
待处理 run 数、执行中 run 数、最老待处理时长、24 小时结束数 / 失败数 / 失败率 |
schedules |
定时任务总数、启用数、执行中数、最近一次失败的启用任务、24 小时失败运行数 |
单个路径的 statfs 或哨兵检查超过 3 秒记 timeout:磁盘段标 critical,挂载段标 timeout。请求本身不会被卡住。
GET /system/health/history?hours=
hours取 1–168,缺省 6。- 按桶聚合,每条序列最多约 360 个点。桶宽最小 15 秒,168 小时时是 1680 秒。
- 每个进程一条序列,每个点有
lagMs(桶内平均)、lagMaxMs(桶内最大)、runningRuns、sseConnections。
告警阈值建议
- 进程
stale:warn。连续 2 分钟仍 stale 就去查容器状态和日志。 - 没有任何存活的 worker / all 进程:warn。任务不会被执行。
- 事件循环最大延迟 ≥ 1 秒记 warn,≥ 5 秒记 critical。延迟接近 15 秒时,引擎租约有丢失风险。
- DB 延迟 ≥ 100 ms 或连接数 ≥ 75%
max_connections记 warn;≥ 500 ms 或 ≥ 90% 记 critical。 idle in transaction连接超过 5 个记 warn,通常是有事务没提交。- 磁盘用量 ≥
cache.resumePercent(缺省 85%)记 warn,≥cache.hardThresholdPercent(缺省 90%)记 critical。 - 挂载根
offline或timeout:critical。先查宿主机挂载,再查哨兵文件。 - 最老待处理 run 等待 ≥ 5 分钟记 warn,≥ 30 分钟记 critical。通常是 worker 没起来或并发被占满。
- 24 小时失败率 ≥ 10% 记 warn;失败率 ≥ 30% 且结束数 ≥ 10 记 critical。
- 有启用的定时任务最近一次运行失败:warn。
引擎 runs 的业务字段
GET /engine/runs 和 GET /engine/runs/{id} 的每个 run 多了 business,推断不出时为 null:
{ "kind": "feed", "refId": "<feed_source.id>", "title": "HDSky RSS", "triggeredBy": "event" }
kind:subscription/download/organization/agent/schedule/feed/site/decision/media。refId:业务对象 id;schedule是定时任务 key(如trash.purge)。download优先指向下载任务,计划还没提交时指向收录计划 id。title:业务对象的展示名。对象已删除时为 null。triggeredBy:user/api_key/schedule/agent/event,推断不出为 null。
kind 与 refId 的推断顺序(auth-settings/engine-business.ts,列表筛选和展示用同一条 SQL 表达式):
- run 输入里的业务 id 键:
agentRunId、recordId、downloadTaskId、acquisitionPlanId、subscriptionId、acquisitionSlotId、feedSourceId、siteId、accountId(换成站点)、decisionId、mediaEntityId。 - 业务任务行
task(engine_run_id= run id)的subject_type/subject_id。 - 没有业务 id 的定时任务(
purgeTrash、refreshPiTokens、cleanupDownloadCache、reconcileLibrary),且幂等键不是手动或重跑。
triggeredBy 的推断顺序:
- Agent 会话看
agent_run.trigger。 - 看
task.triggered_by。 - 幂等键是
retry:或含manual的记为user。 - 引擎幂等键能对上 outbox 事件的记为
event。 - 调度器时间槽键记为
schedule。
筛选参数:businessKind、businessRefId,可以一起用。这两个参数对每行都要算一次推断表达式,runs 很多时要带上时间范围。