本文:在 Go 后端构建可观测性(Prometheus + Tracing + 日志)
在 Go 后端构建可观测性(Prometheus + Tracing + 日志)
发布时间: 2025-08-23 (a year ago)
GO

本文:在 Go 后端构建可观测性(Prometheus + Tracing + 日志)

一、总体架构建议

为了把可观测性整合到现有项目(config/core/models/service/routers/middleware),建议采用三层监控方案:

  1. 指标(Metrics):Prometheus 指标用于量化系统的健康与性能。埋点位置通常在 HTTP 层、数据库访问、外部 API 调用和关键业务逻辑。
  2. 日志(Logging):结构化日志(例如 zap)用于记录请求上下文、错误堆栈与重要事件,用于审计与交叉验证指标。
  3. 分布式追踪(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_totalappname_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% 或基于错误/慢请求采样)。
  • 常见工具链:OpenTelemetry Collector -> Jaeger/Zipkin 或直接导出至云厂商的 APM 服务。

五、Alert 策略与 SLO

  • 指标到告警的建议:

    • 关键业务错误率(5 分钟内 error_rate > threshold)
    • 请求 P95/P99 延迟异常上升
    • 主从数据库延迟、连接池耗尽
    • 磁盘/磁盘使用率、队列积压
  • 把 SLO(服务等级目标)写成可测量的指标,例如“99.9% 的请求 P95 时延 < 500ms”。告警按 SLO 违背程度分为 P0/P1/…

六、在现有架构中的落地步骤(按优先级)

  1. 初始化 logger(结构化)并在所有模块统一使用。
  2. core 初始化 Prometheus client 与 tracer SDK,并创建 /metrics/healthz 接口。
  3. middleware 中埋点(请求计数、时延、状态码、trace 注入)。
  4. service 层为关键业务添加业务指标(计数器/直方图)。
  5. 配置 Prometheus 抓取并在 Grafana 上建立基础 dashboard(HTTP QPS、错误率、P95/P99、DB latency)。
  6. 逐步引入 tracing,并在生产选择低采样率先观测关键路径。

七、实操示例(高层伪代码,避免泄露真实源码)

  • Middleware 埋点思路:

    1. 从请求 header 中读取或生成 request_id/trace_id。
    2. 在 context 中存储这些 id 并开始一个 span。
    3. 记录请求开始时的时间,完成后更新 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。分阶段上线并验证。

十、结语

可观测性是使系统可维护、可诊断的核心能力。把它作为工程化的一部分,从一开始就设计(而不是事后补救),会大幅降低排障成本与事故影响面。