2. 可观测性三大支柱:指标、日志、链路追踪的核心原理与数据模型
可观测性(Observability)的工程实践通常围绕三大数据支柱展开:指标(Metrics)、日志(Logs)和链路追踪(Traces)。这三者并非相互替代,而是从不同维度描述系统状态,共同构成完整的可观测性拼图。理解每种支柱的核心原理与数据模型,是设计租户隔离架构的前提。
2.1 三大支柱概述与对比
下表从数据本质、采集方式、存储模型和典型用途四个维度,对三大支柱进行横向对比:
| 维度 | 指标(Metrics) | 日志(Logs) | 链路追踪(Traces) |
|---|---|---|---|
| 数据本质 | 聚合的数值时间序列 | 离散的、带时间戳的文本/结构化事件 | 请求在分布式系统中的完整执行路径 |
| 采集方式 | 定期拉取(Pull)或推送(Push) | 事件触发写入(Push) | 请求上下文传播 + 采样(Push) |
| 存储模型 | 时序数据库(如 Prometheus TSDB) | 倒排索引 + 全文搜索(如 Elasticsearch) | Span 树 + 关联存储(如 Jaeger/ Tempo) |
| 典型用途 | 告警、趋势分析、容量规划 | 故障排查、审计、详细事件分析 | 性能瓶颈定位、依赖关系分析 |
2.2 指标(Metrics)核心原理与数据模型
指标是系统状态的“快照”,以数值形式周期性记录。其核心优势在于低存储成本和高查询效率,适合用于告警和趋势分析。
2.2.1 数据模型:时间序列
指标的核心数据模型是时间序列(Time Series),由以下三要素唯一标识:
- 指标名称(Metric Name):描述被测量对象,如
http_requests_total。 - 标签(Labels):键值对,用于维度描述,如
{method="GET", endpoint="/api/v1/users", tenant="acme"}。 - 时间戳与值(Timestamp & Value):一个时间点对应的数值。
一个典型的时间序列标识如下:
http_requests_total{method="POST", status="200", tenant="tenant_a"} @ 1700000000 = 1024
2.2.2 指标类型
Prometheus 定义了四种核心指标类型,每种类型对应不同的聚合语义:
| 类型 | 说明 | 典型场景 |
|---|---|---|
| Counter(计数器) | 只增不减的累计值 | 请求总数、错误总数 |
| Gauge(仪表盘) | 可增可减的瞬时值 | CPU 使用率、内存占用、并发连接数 |
| Histogram(直方图) | 对观测值进行分桶统计 | 请求延迟分布(如 p50/p99) |
| Summary(摘要) | 类似 Histogram,但计算分位数 | 服务端预计算的分位延迟 |
tenant 标签是隔离的关键。必须确保所有指标都携带租户标签,否则不同租户的数据会混在一起,导致告警误报或数据泄露。
2.3 日志(Logs)核心原理与数据模型
日志是系统产生的离散事件记录,提供最详细的上下文信息。在故障排查和安全审计中,日志是不可或缺的证据链。
2.3.1 数据模型:结构化日志
现代可观测性平台普遍采用结构化日志(Structured Logging),而非纯文本日志。结构化日志将事件拆分为多个字段,便于索引和查询。
一个典型的结构化日志条目(JSON 格式)如下:
{
"timestamp": "2024-01-01T12:00:00Z",
"level": "ERROR",
"logger": "com.example.payment.PaymentService",
"message": "Payment processing failed",
"tenant_id": "tenant_b",
"trace_id": "abc123def456",
"user_id": "user_789",
"amount": 99.99,
"error_code": "INSUFFICIENT_FUNDS"
}
2.3.2 日志级别与分类
日志级别用于区分事件的严重程度,常见的级别体系如下:
- TRACE / DEBUG:细粒度调试信息,通常只在开发环境开启。
- INFO:正常业务流程记录,如请求开始、结束。
- WARN:潜在问题,但不影响当前功能,如重试、降级。
- ERROR:功能异常,需要人工介入,如数据库连接失败。
- FATAL:严重错误,导致系统不可用。
tenant_id 作为必填字段注入到每条日志中。在存储端(如 Elasticsearch),使用 tenant_id 作为索引路由(Routing)或索引前缀,实现物理或逻辑隔离。
2.4 链路追踪(Traces)核心原理与数据模型
链路追踪用于追踪一个请求在分布式系统中的完整执行路径。它通过上下文传播(Context Propagation)将跨服务的调用串联起来,形成一棵 Span 树。
2.4.1 核心概念:Trace 与 Span
- Trace(追踪):代表一个完整的请求或事务,由多个 Span 组成,通过全局唯一的
Trace ID标识。 - Span(跨度):代表 Trace 中的一个工作单元,记录一个服务或组件处理该请求的起止时间、状态和元数据。每个 Span 有唯一的
Span ID,并通过Parent Span ID关联父 Span。
2.4.2 数据模型:Span 树
一个 Trace 的数据模型本质上是一棵有向无环图(DAG),根 Span 代表入口请求,子 Span 代表下游调用。一个 Span 的核心字段包括:
| 字段 | 说明 | 示例 |
|---|---|---|
trace_id |
全局唯一追踪 ID | abc123def456 |
span_id |
当前 Span 的唯一 ID | span_001 |
parent_span_id |
父 Span 的 ID(根 Span 为空) | span_000 |
service_name |
产生该 Span 的服务名 | payment-service |
operation_name |
操作名称 | POST /api/payments |
start_time / duration |
开始时间与持续时长 | 1700000000 / 150ms |
tags |
键值对元数据 | tenant_id: tenant_c |
2.4.3 上下文传播机制
链路追踪的核心在于上下文传播。当服务 A 调用服务 B 时,必须将当前的 Trace ID 和 Span ID 通过 HTTP Header(如 traceparent)或 RPC 元数据传递给下游服务,下游服务才能将新的 Span 挂接到同一个 Trace 树上。
tags 或 baggage 实现。将 tenant_id 作为 Span 的 Tag 或 Baggage 项传播,确保所有 Span 都能关联到正确的租户。在查询时,通过 Trace ID 关联的租户标签进行过滤。
2.5 三大支柱的关联与融合
在实际的可观测性平台中,三大支柱并非孤立存在,而是通过关联机制形成合力:
- Trace ID 关联:在日志和指标中注入
trace_id字段,实现从指标告警 -> 查看相关日志 -> 定位具体 Trace 的快速跳转。 - 租户 ID 统一:所有数据源统一使用
tenant_id作为核心标签/字段,确保跨数据源的租户隔离策略一致。 - 服务名对齐:指标、日志和 Trace 中的
service_name必须保持一致,避免数据孤岛。