跳到主要内容

可观测性

OCM 的可观测性按「信号层归上游、消费层跟部署情景走、交付层归交付方」分层:

  • 信号层(上游,部署无关):后端暴露 Prometheus 格式的 /metrics 端点 (RED 请求指标 + Go 运行时 + DB 连接池)、结构化 JSON 日志(stdout)、 /healthz 与 /readyz 探针、以及每个响应携带的 X-Request-ID。
  • 消费层(跟部署情景走):Docker Compose 情景用参考监控栈 overlay (本文档);Serverless 云原生情景没有 node_exporter/Prometheus 守护进程 的生存空间,信号层交给平台托管监控消费——平台收 stdout 日志、探 healthz、抓 /metrics。
  • 交付层(归交付方):面板调优、告警路由、runbook、运维账号,每个 部署站点各不相同。

信号层(后端)​

METRICS_ADDR​

环境变量默认说明
METRICS_ADDR未设即关闭/metrics 独立监听地址(如 :9091)
  • 独立 mux、独立监听:/metrics 不在业务 mux 上,第二个监听器永远 不会误暴露业务路由;监听失败只记日志,不拖垮 API 主服务。
  • 暴露内容(Prometheus 文本格式):
    • http_requests_total{method,path,status} — RED 的 R/E,path 是 ServeMux 路由 pattern(如 GET /api/roles/{id}),不是原始 URL, 基数有界;未匹配路由记为 unmatched。
    • http_request_duration_seconds_bucket/sum/count{method,path} — p95/p99 由它派生。
    • http_requests_in_flight — 进行中请求数。
    • ocm_db_* — 连接池开/闲/占用/上限/等待计数与等待时长。
    • go_* / process_* — Go 运行时与进程指标(client_golang 默认注册)。
  • 无鉴权是设计使然:依赖网络隔离。它绝不能发布到宿主机公网接口 (overlay 已遵守;自组部署时同样遵守)。

X-Request-ID​

AccessLog 中间件给每个响应(含 4xx/5xx 错误响应)打上 X-Request-ID 响应头,与日志行的 request_id 同源。运维或最终用户 遇到错误时引用该 id,即可在日志(面板/Loki/容器日志)中精确定位那一次 请求——这是「运维反馈错误 → 开发定位」闭环的关键一环。

日志​

slog JSON 打 stdout(生产默认 JSON,LOG_LEVEL/LOG_FORMAT 可调), 容器平台原生采集。业务审计记录在 system_logs(数据库),与运维日志 互不掺杂。

Compose 参考监控栈​

docker compose -f docker-compose.yml -f docker-compose.observability.yml up -d # dev
docker compose -f docker-compose.prod.yml -f docker-compose.observability.yml up -d # prod
服务镜像(已钉版本)作用端口
prometheusprom/prometheus:v3.13.3 (LTS)抓取 + 存储内网 9090
grafanagrafana/grafana:13.2.2运维面板发布 :3000
node-exporterprom/node-exporter:v1.12.1主机 CPU/内存/磁盘内网 9100
lokigrafana/loki:3.7.8日志存储(30 天保留)内网 3100
alloygrafana/alloy:v1.20.0容器日志采集进 Loki无
  • 配置都在 deploy/observability/(见其 README)。
  • Grafana 开箱即用「OCM 服务状态总览」面板:服务在线、请求速率、5xx、 p95 延迟、CPU/内存/磁盘、DB 连接池、最近后端错误日志(反馈流程: 复制日志行里的 request_id 反馈给开发)。
  • GRAFANA_ADMIN_PASSWORD 必填(.env 或环境变量),缺省拒绝启动。

安全基线​

  1. 只有 Grafana 对外。/metrics、node-exporter、prometheus、loki 仅 compose 内网可达,不得发布宿主机端口。
  2. Grafana 强密码 + HTTPS 反向代理之后交付;运维角色视为只读(重启等 维护动作走 runbook,不开面板权限)。
  3. 面板不接 system_logs 业务审计(含学生数据);错误日志面板只看 stdout 运行日志(method/path/status/user 登录名,无业务数据)。
  4. 监控栈独立于被监控对象存活:backend 全挂时,主机指标、探针状态、 up == 0 告警照常工作。

为什么不是 OpenTelemetry​

单进程架构(MQTT 消费者是进程内 goroutine)没有跨进程 trace 需求; /metrics 直出 Prometheus 是移动部件最少的方案。拆出第二个常驻进程 (如独立部署的 worker/consumer)之日,才是引入 OTel collector 之时—— 届时 OTLP → collector → Prometheus,/metrics 端点与本 overlay 的面板 原样保留,只是数据来源多一条管道。