# 队列监控接入说明(A6-INF-01) 本目录提供 BullMQ 队列与 Outbox 投递的 Prometheus 告警规则。M0 阶段**只交付指标端点与规则文件**, 本机尚未部署 Prometheus / Grafana(技术架构 §4 的观测套件在 T1 阶段落地),后续按下面的步骤接入。 ## 1. 指标端点 | 用途 | 地址 | 说明 | | --------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------- | | Prometheus 抓取 | `GET /api/v1/metrics` | `text/plain; version=0.0.4; charset=utf-8`,由 `apps/api/src/infra/queue/queue-metrics.controller.ts` 提供 | | 队列健康检查 | `GET /api/v1/health/queues` | 9 个队列的计数 / 队首等待秒数 / worker 心跳;Redis 不可用返回 503(错误码 50002) | `/health/queues` 的 HTTP 状态:依赖异常 503;`status=degraded`(存在积压但 worker 心跳缺失或陈旧)仍返回 200,由告警规则负责通知。 指标采集失败不会让 `/metrics` 返回 5xx,而是输出 `#` 注释行并记日志,保证抓取链不断。 > 注意:`/health`、`/metrics` 均为**只读公开端点**(`@Public()`),部署时应在网关限制为内网访问; > 进程启动时 `@nestjs/swagger` 会扫描控制器,`/metrics` 已用 `@ApiExcludeController()` 排除出 OpenAPI 契约。 ## 2. 指标清单 | 指标 | 类型 | 标签 | 含义 | | ------------------------------------- | ----- | ----------------------------------------------------------- | ------------------------------------------------------- | | `lingxi_queue_jobs` | gauge | `queue`、`state`(waiting/active/completed/failed/delayed) | 队列内各状态任务数 | | `lingxi_queue_oldest_waiting_seconds` | gauge | `queue` | 队首等待任务的等待秒数(无等待任务为 0) | | `lingxi_queue_failure_ratio` | gauge | `queue` | `failed/(failed+completed)`,无样本为 0 | | `lingxi_worker_heartbeat_age_seconds` | gauge | `queue` | worker 心跳年龄(秒);缺失为 `-1` | | `lingxi_outbox_pending_total` | gauge | — | `outbox_events.published_at IS NULL` 的事件数 | | `lingxi_outbox_dead_letter_total` | gauge | — | `outbox_events.last_error='dead_lettered'` 的累计事件数 | 心跳 key:`lingxi:worker:heartbeat:`(worker 每 10s 续写,TTL 30s)。 > 队列名口径:指标 / 告警 / 心跳 / `QUEUE` 环境变量都用**逻辑名**(`media:verify` 这类 `<域>:<动作>`); > BullMQ 5.x 禁止队列名与自定义 jobId 含冒号,因此 BullMQ 内部物理队列名把 `:` 换成 `-`(`media-verify`), > jobId 用 `-` 连接(`-`)。排查 Redis key 时按物理名找,看指标与告警时按逻辑名。 ## 3. Prometheus 接入步骤 1. 启动 Prometheus(本机示例;生产按运维 Runbook 挂到 Compose): ```yaml # prometheus.yml scrape_configs: - job_name: lingxi-api metrics_path: /api/v1/metrics static_configs: - targets: ['127.0.0.1:3000'] ``` ```bash prometheus --config.file=prometheus.yml \ --rules.file=infra/monitoring/queue-alerts.yml # 或使用 rule_files 引入 ``` > `rule_files` 更常用:在 `prometheus.yml` 写 `rule_files: ['/etc/prometheus/queue-alerts.yml']`。 > 本仓库的 CI / 本地校验可用 `promtool check rules infra/monitoring/queue-alerts.yml`。 2. 校验规则语法: ```bash promtool check rules infra/monitoring/queue-alerts.yml ``` 3. 验证数据:`curl -s http://127.0.0.1:3000/api/v1/metrics | grep lingxi_`, 再在 Prometheus UI → Graph 查询 `lingxi_queue_oldest_waiting_seconds`。 ## 4. 告警规则 | 告警 | 表达式 | 持续 | 级别 | 处置 | | ------------------------------ | ------------------------------------------- | ---- | -------- | ----------------------------------------------------------------------------------------------------- | | `LingxiQueueBacklog` | `lingxi_queue_oldest_waiting_seconds > 600` | 5m | warning | 确认对应队列组的 worker 是否启动 / 并发是否被长任务占满;必要时扩容 worker(`QUEUE=<组名>` 单独扩容) | | `LingxiQueueHighFailureRatio` | `lingxi_queue_failure_ratio > 0.05` | 10m | warning | 看失败 job 的 `last_error` 与 worker 日志;区分业务失败与依赖故障 | | `LingxiWorkerHeartbeatMissing` | `heartbeat_age < 0` 或 `> 60` | 2m | critical | 检查 worker 进程 / `QUEUE` 分组 / Redis 连通性 | | `LingxiOutboxDeadLetter` | `lingxi_outbox_dead_letter_total > 0` | 1m | critical | 查 `outbox_events WHERE last_error='dead_lettered'`,修复 payload / 队列配置后人工补投 | ## 5. Grafana(后续) - 数据源:Prometheus;面板建议:按 `queue` 分组的任务数堆叠图、队首等待时长、 失败率、worker 心跳热力图、outbox 待投递 / 死信。 - 本机暂无 Grafana 实例,M0 验收只要求 `curl /api/v1/metrics` 可读到上述指标、规则文件可加载。