3. 可观测性三大支柱:日志、指标、链路追踪概述

在多租户后端系统中,可观测性并非单一工具或数据源能够支撑。业界公认的三大支柱——日志(Logging)、指标(Metrics)、链路追踪(Tracing)——各自从不同维度描述系统状态,共同构成完整的可观测性数据平面。理解三者的定义、数据特征、适用场景及租户隔离方式,是设计多租户可观测性架构的基础。

3.1 三大支柱核心概念与数据特征

下表从数据格式、存储模型、典型用途和租户隔离粒度四个维度,对三大支柱进行横向对比:

维度 日志(Logging) 指标(Metrics) 链路追踪(Tracing)
数据格式 非结构化/半结构化文本(JSON、纯文本) 结构化数值 + 标签(Label/Tag) 结构化 Span(TraceID + SpanID + 父SpanID)
存储模型 倒排索引 + 时间序列(如 Elasticsearch) 时序数据库(如 Prometheus TSDB) 图结构 + 时间序列(如 Jaeger、Tempo)
典型用途 故障根因分析、审计、调试 告警、容量规划、SLO 监控 请求路径分析、性能瓶颈定位
租户隔离粒度 索引/命名空间 + 字段级租户标签 Metric 标签 + 租户前缀 Span 标签 + 采样策略按租户配置
数据量级 极高(GB~TB/天) 中等(MB~GB/天) 中等(取决于采样率)
关键认知:三大支柱不是替代关系,而是互补关系。日志回答“发生了什么”,指标回答“有多少/多严重”,链路追踪回答“具体在哪里/为什么慢”。多租户场景下,三者必须共享统一的租户身份上下文,才能实现跨数据源的关联分析。

3.2 日志(Logging):事件记录的基石

日志是系统运行时产生的离散事件记录,通常包含时间戳、严重级别、来源模块和详细消息。在多租户架构中,日志面临的核心挑战是租户数据混部与存储成本控制。

  • 结构化日志:强制使用 JSON 格式,包含 tenant_id、request_id、service_name 等标准字段,便于后续过滤与租户隔离查询。
  • 日志分级与采样:ERROR 级别全量保留,WARN 级别按租户配额采样,INFO/DEBUG 级别在低流量时段或按需开启。
  • 租户隔离策略:采用“共享存储 + 索引隔离”模式,每个租户拥有独立的日志索引或命名空间,避免跨租户数据泄露。
// 结构化日志示例(Go 语言)
log.WithFields(log.Fields{
    "tenant_id":  "tenant-abc-123",
    "request_id": "req-456-def",
    "service":    "payment-service",
    "duration_ms": 245,
}).Info("Payment processed successfully")

3.3 指标(Metrics):聚合数据的量化视图

指标是系统状态在时间轴上的数值聚合,适合用于告警、趋势分析和容量规划。多租户场景下,指标设计的关键在于标签(Label)策略与聚合层级。

  • 租户标签注入:每个指标必须携带 tenant_id 标签,支持按租户维度查询和聚合。
  • 指标类型:Counter(累计计数)、Gauge(瞬时值)、Histogram(分布统计)、Summary(分位数)。
  • 聚合层级:全局聚合(平台级)、租户级聚合(按 tenant_id)、服务级聚合(按 service_name)。
实践建议:避免高基数标签(如 user_id、request_id)直接作为指标标签,否则会导致时序数据库性能急剧下降。高基数数据应通过日志或链路追踪承载,指标只保留租户、服务、区域等有限维度。

3.4 链路追踪(Tracing):请求全路径的可视化

链路追踪通过 Trace 和 Span 记录一次请求在分布式系统中的完整调用路径。多租户场景下,链路追踪需要解决采样策略的租户差异化和上下文传播的租户身份绑定。

  • Trace 与 Span:一个 Trace 由多个 Span 组成,每个 Span 代表一个服务调用或内部操作,包含开始时间、结束时间、状态和标签。
  • 上下文传播:通过 W3C Trace Context 或 Zipkin B3 协议,在服务间传递 trace_id、span_id 和 tenant_id。
  • 采样策略:高价值租户(付费用户)使用全量采样,普通租户使用头部采样(Head-based Sampling)或尾部采样(Tail-based Sampling)。
// 链路追踪 Span 创建示例(OpenTelemetry)
tracer := otel.Tracer("payment-service")
ctx, span := tracer.Start(ctx, "process-payment",
    trace.WithAttributes(
        attribute.String("tenant_id", "tenant-abc-123"),
        attribute.String("payment_method", "credit_card"),
    ),
)
defer span.End()

3.5 三大支柱协同关系与多租户架构图

下图展示了三大支柱在多租户后端系统中的协同工作方式,以及各自的数据采集、存储与查询路径:

可观测性三大支柱协同架构(多租户场景) 应用服务 (多租户实例) 日志(Logging) 指标(Metrics) 链路追踪(Tracing) 日志存储 (ES/Loki) 时序数据库 (Prometheus/Thanos) Trace 存储 (Jaeger/Tempo) 统一查询与关联分析层 租户隔离关键点 日志:索引/命名空间隔离 + tenant_id 字段过滤 指标:tenant_id 标签 + 租户级聚合视图 链路追踪:Span 标签 + 按租户差异化采样策略

3.6 三大支柱的关联分析:从孤岛到融合

在多租户可观测性实践中,三大支柱并非独立运行。通过统一的 租户身份上下文 和 请求标识(TraceID),可以实现跨数据源的关联分析:

  1. 日志 ↔ 链路追踪:日志中记录 trace_id,当发现错误日志时,可直接跳转到对应 Trace 查看完整调用链。
  2. 指标 ↔ 链路追踪:指标告警触发后,通过 tenant_id 和 service_name 过滤出相关 Trace,定位慢调用或错误请求。
  3. 日志 ↔ 指标:日志中的错误计数可作为自定义指标输出,用于告警规则配置。
常见陷阱:三大支柱的数据源如果使用不同的租户标识格式(如日志用 tenant_id,指标用 tenantId,链路追踪用 tenant-id),将导致关联分析失败。必须在全平台统一租户标识的字段名和格式,建议使用 tenant_id 作为标准字段。

3.7 多租户场景下的选型建议

下表总结了三大支柱在不同多租户需求下的技术选型参考:

需求场景 推荐方案 租户隔离方式 注意事项
合规审计(日志) Elasticsearch + 租户索引 索引级隔离 + 字段过滤 注意存储成本,设置日志保留策略
实时告警(指标) Prometheus + Thanos 标签隔离 + 租户级 Recording Rules 避免高基数标签导致性能问题
性能诊断(链路追踪) OpenTelemetry + Jaeger Span 标签 + 按租户采样率 高流量租户需独立采样策略
全栈可观测性 Grafana + Loki + Tempo + Mimir 统一租户标签 + 数据源代理 需要统一的数据源路由层