# Prometheus 系统监控设计 > 版本:V1.0
> 设计日期:2026-08-14
> 适用范围:运营端 → 系统管理 → 系统监控
> 实施边界:使用平台原生 React UI,不引入 Grafana、Netdata、Zabbix 或 Prometheus 自带 UI ## 1. 建设目标 运营人员需要在现有权限体系和视觉体系内查看服务器硬件资源、核心服务状态、历史趋势和活动告警。Prometheus 仅承担指标抓取、时序存储、PromQL 计算和告警规则执行;浏览器只访问 CMPP 平台 NestJS API,不直接访问 Prometheus、Node Exporter 或 Alertmanager。 第一版解决以下问题: 1. 统一查看 CPU、内存、根文件系统、网络流量、负载和运行时长。 2. 查看 `cmpp-api`、`cmpp-gateway`、PostgreSQL、Redis、MinIO、Nginx 六类核心服务状态。 3. 在近 1 小时、近 24 小时、近 7 天之间切换真实历史趋势。 4. 查看 Prometheus 当前 firing/pending 告警,不在前端伪造阈值判断。 5. Prometheus 不可用、查询超时或指标缺失时明确展示“监控不可用/暂无指标”,不得回退静态值、Mock 或 localStorage。 ## 2. 非目标与边界 - 第一版不提供任意 PromQL 控制台,避免越权查询、高基数查询和资源耗尽。 - 第一版不提供告警确认、备注和关闭操作;需要审计留痕的告警处置另立需求并增加 PostgreSQL 模型。 - 第一版不采集短信正文、手机号、账号、密钥、数据库查询文本或日志原文。 - 云主机通常只能提供虚拟 CPU、内存、云盘和虚拟网卡指标;风扇、物理温度、电源、RAID 和物理硬盘 SMART 需 IPMI/Redfish 或厂商接口,未接入时不得显示伪造数据。 - Prometheus、Node Exporter 和 Alertmanager 不暴露在公网;仅 API 服务端可以访问 Prometheus。 ## 3. 总体架构 ```mermaid flowchart LR Node["Node Exporter\n主机与 systemd 指标"] --> Prom["Prometheus\n抓取、存储、PromQL、告警规则"] API["NestJS 监控模块\n固定查询模板与响应归一化"] --> Prom UI["运营端原生 React UI"] --> API Prom --> Alert["Prometheus 活动告警"] Alert --> API ``` 数据流必须是 `Exporter → Prometheus → NestJS → 运营端`。前端不得直接拼接 Prometheus URL,不得保存 Prometheus Token,不得接受服务端返回的原始 PromQL。 ## 4. 采集与部署设计 ### 4.1 Node Exporter Node Exporter 仅监听 `127.0.0.1:9100`,启用默认 CPU、内存、文件系统、磁盘、网络、负载和启动时间采集器,并显式启用 `systemd` 采集器。systemd 只允许采集: - `cmpp-api.service` - `cmpp-gateway.service` - `postgresql.service` - `redis.service` 或 `redis-server.service` - `cmpp-minio.service` - `nginx.service` 排除 `/dev`、`/proc`、`/sys`、`/run` 等伪文件系统和临时挂载,避免磁盘指标重复和高基数。 ### 4.2 Prometheus - 仅监听 `127.0.0.1:9090`。 - 默认每 15 秒抓取一次,查询超时 5 秒。 - 第一版保留 30 天或不超过 8GB 的时序数据,达到任一边界即按 Prometheus TSDB 策略清理。 - 配置文件由仓库 `tools/monitoring/` 管理;安装脚本只安装、校验和启动监控服务,不重启 CMPP Gateway 或发送 Worker。 - 生产环境变量使用 `PROMETHEUS_URL=http://127.0.0.1:9090`,API 不向响应透出该地址。 ### 4.3 告警规则 规则使用持续窗口而非瞬时尖峰: | 告警 | Warning | Critical | |---|---:|---:| | 主机指标失联 | — | 连续 2 分钟无数据 | | CPU 使用率 | 连续 10 分钟 > 85% | 连续 5 分钟 > 95% | | 内存使用率 | 连续 10 分钟 > 85% | 连续 5 分钟 > 95% | | 根文件系统使用率 | 连续 15 分钟 > 80% | 连续 5 分钟 > 90% | | inode 使用率 | 连续 15 分钟 > 80% | 连续 5 分钟 > 90% | | CPU iowait | 连续 10 分钟 > 20% | 连续 10 分钟 > 35% | | 核心 systemd 服务 | — | 非 active 2 分钟 | 告警标签至少包含 `alertname`、`severity`、`instance`、`service`;注解至少包含中文 `summary`、`description`、`currentValue`、`threshold`。敏感环境变量和凭据不得进入标签或注解。 ## 5. 后端设计 ### 5.1 API ```text GET /api/admin/infrastructure-monitoring/overview?range=1h|24h|7d ``` 该接口受现有运营端 Session 中间件保护,仅提供只读数据。`range` 只接受白名单;非法值返回 400。 ### 5.2 固定查询 后端维护具名查询表,不接受前端 PromQL: - CPU:非 idle CPU 秒率。 - 内存:`1 - MemAvailable / MemTotal`。 - 根文件系统:`1 - available / size`。 - 网络:排除 loopback 后的收发字节率。 - 负载:`node_load1`。 - 运行时长:当前时间减 `node_boot_time_seconds`。 - 服务:指定 unit 的 `node_systemd_unit_state{state="active"}`。 - 告警:Prometheus `/api/v1/alerts`。 瞬时查询和区间查询并行执行。区间步长固定为:1小时/60秒、24小时/300秒、7天/1800秒;后端最多返回约 340 个点/序列,禁止浏览器控制步长。 ### 5.3 可用性与错误语义 - Prometheus 查询成功:`available=true`,返回真实指标、服务和告警。 - Prometheus 未配置、拒绝连接、超时、返回非成功状态或响应结构非法:`available=false`,返回采集时间和安全错误摘要,指标字段为 `null`、趋势为空数组。 - 单个指标不存在不影响其他指标,缺失项为 `null`;不得把缺失解释为 0。 - 服务状态使用 `healthy/unhealthy/unknown`,只有明确采集到 active 才是 healthy,明确采集到 0 才是 unhealthy,指标缺失是 unknown。 ### 5.4 安全控制 - Prometheus URL 由服务端环境变量读取并限制为 `http://127.0.0.1` 或明确配置的内网 HTTPS 地址。 - 每次请求设置 5 秒 AbortSignal 超时。 - 不记录完整响应体;错误日志不得包含URL中的认证信息。 - 不允许前端传 query、step、start、end 或 Prometheus 标签选择器。 - 不将监控指标复制进业务 PostgreSQL,避免高频写入和业务库膨胀。 ## 6. 前端信息架构 页面路由为 `/admin/system-monitoring`,保留原 `/admin/monitor` “发送监控”,两者业务含义不得混用。 ### 6.1 页面结构 1. 页面标题、最近采集时间、刷新按钮、1小时/24小时/7天范围切换。 2. 横向健康概览:整体状态、服务总数、正常、警告、严重、活动告警。 3. CPU、内存、磁盘、网络四项资源区:当前值、辅助值和当前范围趋势。 4. 服务状态侧栏:六类服务、状态和最新采集时间。 5. 活动告警表:名称、级别、开始时间、持续时间、当前值、阈值。 6. 下方资源趋势:CPU、内存、磁盘和网络收发的完整趋势图。 ### 6.2 视觉规格 - 复用现有 `surface`、`Button`、`Tag`、`Table`、`Chart` 和主题变量。 - 真白背景、低饱和蓝色主色、冷灰边框;正常/警告/严重使用既有语义色。 - 不使用第三方Logo、iframe、暗色监控皮肤、霓虹渐变或装饰性假指标。 - 桌面优先保持表格和趋势信息密度;1100px 以下两列,780px 以下单列。 - 图表缺失时显示“暂无真实指标”,不能绘制零线冒充数据。 ### 6.3 交互与刷新 - 初次进入立即请求真实接口。 - 可见页面每 30 秒刷新;页面隐藏或 Session 锁定导致组件卸载后停止刷新。 - 切换时间范围立即重新查询并禁用重复点击;手动刷新不改变范围。 - 请求失败保留上一次成功数据会造成陈旧误导,因此本版失败时清空数据并展示不可用状态。 ## 7. 响应契约摘要 ```ts type InfrastructureOverview = { available: boolean; range: '1h' | '24h' | '7d'; collectedAt: string; error?: string; summary: { overallStatus: 'healthy' | 'warning' | 'critical' | 'unknown'; serviceTotal: number; serviceHealthy: number; warningAlerts: number; criticalAlerts: number; activeAlerts: number; }; metrics: { cpuUsagePercent: number | null; memoryUsagePercent: number | null; memoryTotalBytes: number | null; memoryAvailableBytes: number | null; diskUsagePercent: number | null; diskTotalBytes: number | null; diskAvailableBytes: number | null; networkReceiveBytesPerSecond: number | null; networkTransmitBytesPerSecond: number | null; load1: number | null; uptimeSeconds: number | null; }; trends: Record>; services: Array<{ key: string; name: string; unit: string; status: 'healthy' | 'unhealthy' | 'unknown' }>; alerts: Array<{ fingerprint: string; name: string; severity: 'warning' | 'critical' | 'info'; status: string; startedAt: string; summary: string; currentValue?: string; threshold?: string }>; }; ``` ## 8. 验收标准 1. 页面所有指标来自真实 Prometheus API,关闭 Prometheus 后页面明确不可用且没有静态回退。 2. 浏览器网络请求只访问 CMPP API,不访问 9090/9100。 3. 非法 range、任意 PromQL 和自定义 step 均无法进入后端查询。 4. CPU、内存、磁盘、网络当前值与 Prometheus 同时刻查询在允许的采样误差内一致。 5. 六类服务状态与 systemd 指标一致;指标缺失展示未知而非故障或正常。 6. 1小时、24小时、7天切换后时间轴和点数符合固定步长。 7. firing/pending 告警真实展示,告警恢复后不再出现在活动列表。 8. Prometheus/Exporter 只监听本机,公网不能连接 9090/9100。 9. 页面在桌面和移动宽度下无重叠、截断和横向溢出,控制台无相关错误。 10. TypeScript、API专项测试、生产构建、配置校验和 `git diff --check`通过。 ## 9. 服务内部指标扩展(V1.1) ### 9.1 采集边界 - API使用独立回环端口`127.0.0.1:9464/metrics`,采集进程内存、堆内存、事件循环P99、请求量、状态码和延迟直方图。 - Gateway在已有回环控制端口`127.0.0.1:8090/metrics`暴露Go运行时、上下游连接总数、Submit成败和耗时、Redis Stream pending/lag/最旧年龄。 - PostgreSQL、Redis、Nginx使用发行版Exporter;MinIO使用原生Prometheus端点。全部Exporter只监听回环地址。 - 指标标签只允许方法、路由模板、HTTP状态、结果类别和固定服务名。禁止手机号、短信ID、CMPP Msg_Id、任务ID、通道凭据、短信正文、原始URL和SQL文本进入标签。 - 监控页只查询`cmpp:service_*`固定Recording Rules,不为每张卡片执行一条高代价PromQL。 ### 9.2 默认阈值 | 领域 | Warning | Critical | 持续窗口 | |---|---:|---:|---:| | CPU | >80% | >90% | 10m / 5m | | 内存 | >85% | >95% | 10m / 5m | | 磁盘或inode | >80% | >90% | 15m / 5m | | API 5xx | >1%且至少5次 | >5%且至少5次 | 5m | | API P95 | >1s | >3s | 10m / 5m | | API事件循环P99 | >200ms | >1s | 10m / 5m | | Gateway提交队列最旧pending | >30s | >120s | 2m | | Gateway实际上游连接 | — | 少于期朖2m | 2m | | PostgreSQL连接使用率 | >70% | >85% | 10m / 5m | | PostgreSQL死锁 | 15m内>0 | 15m内重复出现 | 1m | | Redis内存/maxmemory | >70% | >85% | 10m / 5m | | Redis淘汰或拒绝连接 | — | 5m内>0 | 1m | | 任一核心Exporter失联 | — | >2m | 2m | | Prometheus采集耗时/周期 | >80% | >100% | 5m | | Prometheus规则计算失败 | — | 5m内>0 | 1m | 比例告警必须带最低样本量,不得把单次失败误报为100%错误率。短信最终回执可由运营商延迟数小时,不纳入Gateway基础设施短窗口Critical,仍由72小时业务终结机制和短信质量看板处理。 ### 9.3 告警收敛与校准 - 主机或Node Exporter失联时,抑制其CPU、内存和磁盘派生告警;API/Gateway指标端点失联时,抑制对应延迟和错误率告警。 - Critical表示需立即处理;Warning表示当日检查;趋势指标未达到可操作条件时只展示,不生成告警。 - 上线后保留7至14天基线,核对业务高峰P95/P99、正常连接数和队列年龄。阈值调整必须同步修改设计、用例、规则和进度记录。 ### 9.4 性能预算 - 全局采集周期保持15秒,无排障需求不降到1秒。 - API和Gateway请求路径只做内存计数、有界直方图和原子计数,不在业务请求中写PostgreSQL或Redis。 - PostgreSQL Exporter只使用发行版默认低代价查询,不采集SQL原文或扫描业务大表。 - 时序仍受30天和8GB双重上限约束;时序增长时先缩短实际保留期,不允许无界占满业务盘。 ## 10. 阈值配置与全局预警入口(2026-08-14 增补) - 可配置范围固定为主机 CPU/内存/根磁盘、API 5xx/P95/事件循环、Gateway 最旧 pending、PostgreSQL 连接、Redis 内存和 MinIO 容量十组警告/严重数值。PromQL、持续窗口、标签和规则文件路径仍由代码固定,浏览器无权提交。 - PostgreSQL 单例记录同时保存期望阈值、生效阈值、配置版本、生效版本和 `applying/effective/failed` 状态。更新使用版本条件认领,防止多个 API 实例并发覆盖;规则先经 promtool 校验,再在同一目录原子替换并调用仅回环开放的 `/-/reload`。失败恢复旧文件并保留旧生效版本。 - 安装器把可配置规则从基础规则中剥离,托管文件归 `cmpp-api:prometheus` 且权限为 0640;Prometheus 仍只监听回环。右上角铃铛只轮询轻量活动告警汇总接口,不重复加载趋势或服务指标。 ## 11. 活动告警已读语义(2026-08-16 增补) - “已读”只表示某位管理员已查看某一次 Prometheus 活动告警,不是 resolve、silence 或 acknowledge 外部告警管理器;页面活动告警总数与平台健康状态仍按 Prometheus 原始 firing/pending 计算。 - 指纹由排序后的 Prometheus labels 稳定生成,`activeAt`区分同一指纹的不同触发周期。数据库以`fingerprint + userId`唯一,upsert同时更新`activeAt/readAt`;读取时只有数据库 activeAt 与当前 Prometheus activeAt 相同才算已读。 - 标记前必须回读当前 Prometheus 告警并校验指纹和 activeAt,防止客户端伪造或把已经恢复的新周期误标已读。预警中心轻量汇总只扣减当前管理员本次已读项;数据库故障不得用 localStorage 或静态状态替代。 ## 12. 历史告警查询(2026-09-09) 新增GET /admin/infrastructure-monitoring/alert-history,继承运营端会话鉴权,参数from/to为上海自然日,默认含今天近7日、最多31日,page正整数、每页25条。逐日查询Prometheus原始ALERTS_FOR_STATE范围向量,以标签指纹+activeAt分开触发周期,跨日采样合并;不使用粗粒度步长丢掉短周期,不把等待触发当作已发送告警。保留真实触发时间和范围内最后观测时间,最后观测不代表准确恢复。 历史和活动列表独立;历史不提供伪造恢复状态、旧annotations、批量已读或清理功能。超出Prometheus保留期/采集缺口的历史无法追溯,界面明确说明。失败返回503并展示错误,日期非法返回400;不迁移数据库、不变更阈值或采集配置。完整实现/验收及限制见operations-fixes-20260909.md。