本文:在 Go 后端构建可观测性(Prometheus + Tracing + 日志)
一、总体架构建议
为了把可观测性整合到现有项目(config/core/models/service/routers/middleware),建议采用三层监控方案:
- 指标(Metrics):Prometheus 指标用于量化系统的健康与性能。埋点位置通常在 HTTP 层、数据库访问、外部 API 调用和关键业务逻辑。
- 日志(Logging):结构化日志(例如 zap)用于记录请求上下文、错误堆栈与重要事件,用于审计与交叉验证指标。
- 分布式追踪(Tracing):使用 OpenTelemetry/OpenTracing 导出到 Jaeger/Zipkin,用于呈现请求调用链、跨服务延迟分布与依赖关系。
把这些能力放在 middleware(HTTP 层埋点、请求时长、trace 注入)、core(初始化 metrics/tracer/logger)与 service(业务级指标)中。
二、指标(Prometheus)落地要点
-
指标类型:
- Counter(计数器):请求总数、错误数、重试次数。
- Gauge(测量值):当前连接数、队列长度、缓存命中率(百分比)。
- Histogram/Summary:请求时延分布、数据库查询时延。Histogram 更适合在 Prometheus 中做聚合。
-
Embedding(示例实践要点):
- 在
core初始化一个全局的 registry 或使用默认 registry。 - 在
middleware中埋请求计数与时延:按路由和状态码打标签(method, route, status)。 - 在
service层为关键业务打业务指标(例如文章发布耗时、评论写入失败率)。
- 在
-
指标命名与标签策略:
- 使用一致的前缀如
appname_http_requests_total、appname_db_query_duration_seconds。 - 标签不要过多,避免高基数(例如不要把 user_id 作为 label)。
- 使用一致的前缀如
-
暴露
/metrics接口:- 仅在内部网络或通过反向代理保护,切勿将裸 metrics 暴露到公网。
-
示例工具链:prometheus(抓取)、grafana(展示)、alertmanager(告警)。
三、结构化日志(zap)与日志关联
-
使用结构化日志(如 zap),约定输出 JSON。字段至少包含:timestamp、level、msg、service、env、trace_id、span_id、请求路径、请求ID。
-
在 middleware 中把 trace_id / request_id 注入到上下文,并在每条日志中输出,以便把日志与 tracing 链接。
-
日志级别策略:
- Debug:开发/调试环境,包含 SQL/headers(敏感数据脱敏)。
- Info:正常运行信息、关键事件。
- Error:错误与异常,包含栈信息(适度)。
-
日志采样:在高流量场景下对 debug/info 做采样,避免日志风暴。推荐在收集端(如 fluentd/Logstash)或 SDK 集成采样器。
四、分布式追踪(OpenTelemetry / Jaeger)
-
目的:追踪请求在应用内部与外部依赖间的延迟与调用顺序,快速定位慢端或依赖问题。
-
关键实践:
- 初始化一个 tracer(在
core),在 HTTP middleware 中为每个请求创建 root span,并将 trace 信息注入 downstream(例如 RPC/HTTP client)。 - 将 trace_id 写入日志与 response header(如
X-Trace-Id),便于排查。 - 采样策略:生产环境选择合适的采样率(例如 1% 或基于错误/慢请求采样)。
- 初始化一个 tracer(在
-
常见工具链:OpenTelemetry Collector -> Jaeger/Zipkin 或直接导出至云厂商的 APM 服务。
五、Alert 策略与 SLO
-
指标到告警的建议:
- 关键业务错误率(5 分钟内 error_rate > threshold)
- 请求 P95/P99 延迟异常上升
- 主从数据库延迟、连接池耗尽
- 磁盘/磁盘使用率、队列积压
-
把 SLO(服务等级目标)写成可测量的指标,例如“99.9% 的请求 P95 时延 < 500ms”。告警按 SLO 违背程度分为 P0/P1/…
六、在现有架构中的落地步骤(按优先级)
- 初始化 logger(结构化)并在所有模块统一使用。
- 在
core初始化 Prometheus client 与 tracer SDK,并创建/metrics与/healthz接口。 - 在
middleware中埋点(请求计数、时延、状态码、trace 注入)。 - 在
service层为关键业务添加业务指标(计数器/直方图)。 - 配置 Prometheus 抓取并在 Grafana 上建立基础 dashboard(HTTP QPS、错误率、P95/P99、DB latency)。
- 逐步引入 tracing,并在生产选择低采样率先观测关键路径。
七、实操示例(高层伪代码,避免泄露真实源码)
-
Middleware 埋点思路:
- 从请求 header 中读取或生成 request_id/trace_id。
- 在 context 中存储这些 id 并开始一个 span。
- 记录请求开始时的时间,完成后更新 Prometheus histogram 和 counter,同时结束 span。
-
Service 指标示例:
article_publish_duration_seconds(histogram)article_publish_failures_total(counter)
八、运维与成本注意事项
- 指标基数:不要将高基数标签放到指标里(如 user_id),否则会导致 Prometheus 存储成本暴涨。
- Tracing 存储成本:采样与保留期需要平衡,完整 trace 存储昂贵,常用采样+索引策略降低成本。
- 日志存储:日志长期保留会产生成本,分级存储(热/冷)和日志裁剪策略是必要的。
九、常见问题 FAQ
Q:metrics 会暴露敏感信息吗?
A:避免在指标 label 中放置敏感或 PII 数据,metrics 应该是汇总级别的数据。
Q:如何把旧服务接入可观测性?
A:先从最容易的开始:结构化日志 -> /metrics -> middleware 埋点 -> tracing。分阶段上线并验证。
十、结语
可观测性是使系统可维护、可诊断的核心能力。把它作为工程化的一部分,从一开始就设计(而不是事后补救),会大幅降低排障成本与事故影响面。