2. OpenTelemetry 指标模型基础:Counter、Histogram、Gauge、UpDownCounter 的概念与数据结构

在深入指标重命名与标签合并之前,必须牢固掌握 OpenTelemetry (OTel) 定义的四种核心指标类型。每种类型都对应特定的数据采集语义和聚合方式,错误的选择会导致监控数据失真。本节将逐一拆解其概念、适用场景及底层数据结构。

2.1 指标类型总览与选择依据

OTel 指标模型围绕“单调性”和“可加性”两个维度定义了四种基础类型。下表从核心特征出发,帮助你在实际埋点中快速决策。

指标类型 单调性 可加性 典型场景 聚合倾向
Counter 单调递增 是 请求总数、错误总数 Sum / Rate
UpDownCounter 可增可减 是 队列长度、活跃连接数 Sum
Histogram 不适用 否(分桶统计) 请求延迟、响应大小 分桶计数 / 分位数
Gauge 无约束 否(快照值) CPU 温度、内存使用量 LastValue
选型口诀: 只增不减用 Counter,可增可减用 UpDownCounter,分布统计用 Histogram,瞬时快照用 Gauge。

2.2 Counter(计数器)—— 单调递增的累积量

Counter 是最常用的指标类型,代表一个只能增加的累积值。它在系统重启或重置时归零,但生命周期内绝不允许减少。典型用例包括 HTTP 请求总数、数据库写入行数、任务执行次数。

数据结构定义

Counter 的数据点由时间戳、值(double 或 int64)和标签集合组成。其核心约束是 delta >= 0。

// OTel Protobuf 简化结构
message CounterDataPoint {
  // 标签列表,用于维度拆解
  repeated KeyValue attributes = 1;
  // 起始时间戳(第一次采集或上次重置)
  fixed64 start_time_unix_nano = 2;
  // 当前采集时间戳
  fixed64 time_unix_nano = 3;
  // 单调递增的累积值
  double value = 4;
  // 可选:指数直方图桶(用于高精度聚合)
  repeated Exemplar exemplars = 5;
}
常见陷阱: 不要用 Counter 记录“当前在线人数”或“队列深度”,因为这些值会下降。下降场景应使用 UpDownCounter 或 Gauge。

2.3 UpDownCounter(上下计数器)—— 可增可减的累积量

UpDownCounter 是 Counter 的泛化版本,允许值增加或减少。它仍然是一个累积量,但 delta 可以为负数。适用于需要追踪“水位”变化的场景,如活跃请求数、待处理消息数、连接池大小。

与 Counter 的核心差异

特性 Counter UpDownCounter
Delta 符号 仅非负 正、负、零
聚合语义 Sum(单调递增) Sum(可波动)
典型后端处理 计算速率(Rate) 直接展示 Sum
重置行为 归零后重新累积 归零后重新累积

2.4 Histogram(直方图)—— 分布统计的基石

Histogram 不记录单个值,而是将观测值分配到预定义的桶(Bucket)中,并记录每个桶的计数。它用于分析数据的分布特征,如 P50/P99 延迟、请求体大小分布。Histogram 是性能监控中最强大的指标类型之一。

数据结构与桶边界

message HistogramDataPoint {
  repeated KeyValue attributes = 1;
  fixed64 start_time_unix_nano = 2;
  fixed64 time_unix_nano = 3;
  // 显式桶边界(递增序列),例如 [0, 10, 50, 100, 500]
  repeated double explicit_bounds = 4;
  // 每个桶的计数,长度 = explicit_bounds + 1
  repeated uint64 bucket_counts = 5;
  // 所有观测值的总和
  double sum = 6;
  // 观测值总数
  uint64 count = 7;
  // 最小值(可选)
  optional double min = 8;
  // 最大值(可选)
  optional double max = 9;
}
关键理解: 桶边界 [0, 10, 50, 100] 会产生 5 个桶:(-∞, 0]、[0, 10)、[10, 50)、[50, 100)、[100, +∞)。bucket_counts[0] 对应第一个桶(小于等于 0 的值)。合理设置桶边界直接影响分位数计算的精度。

2.5 Gauge(仪表盘)—— 瞬时快照值

Gauge 代表一个可以上下波动的瞬时值,没有累积语义。每次采集都是当前状态的快照,后端通常只保留最后一个值(LastValue)。适用于 CPU 使用率、内存占用、磁盘温度等物理或系统指标。

数据结构特点

Gauge 的数据结构是所有指标类型中最简单的,因为它不需要 start_time_unix_nano,也没有桶或累积计数。

message GaugeDataPoint {
  repeated KeyValue attributes = 1;
  fixed64 time_unix_nano = 2;
  double value = 3;  // 瞬时快照值
}

2.6 四种指标的数据流与聚合关系

下图展示了从 SDK 采集到后端聚合的完整数据流,重点突出每种指标在 Collector 或后端中的默认聚合方式。

OTel 四种指标数据流与聚合关系 SDK 采集层 Counter 单调递增累积 UpDownCounter 可增可减累积 Histogram 分桶分布统计 Gauge 瞬时快照值 Collector / 后端聚合 Sum + Rate 计算 Delta → 速率 Sum(可正可负) 直接累加 桶计数 + 分位数 P50 / P99 估算 LastValue 保留最新快照 输出指标数据点 CounterDataPoint UpDownCounterDataPoint HistogramDataPoint GaugeDataPoint 说明:每种指标类型在 SDK 中独立采集,经过 Collector 或后端按语义聚合后,输出为对应的 Protobuf 数据点结构。

2.7 指标数据点通用属性

无论哪种指标类型,其数据点都共享一组通用属性,这些属性在重命名和标签合并操作中至关重要。

  • Name(指标名称): 唯一标识,如 http.server.request_count。重命名操作直接修改此字段。
  • Attributes(标签集合): 键值对列表,如 {method: GET, status: 200}。标签合并操作在此字段上进行。
  • TimeUnixNano(时间戳): 采集时刻的纳秒级 Unix 时间戳。
  • StartTimeUnixNano(起始时间戳): 仅 Counter、UpDownCounter、Histogram 需要,表示累积周期的起点。
  • Value / BucketCounts / Sum / Count: 指标类型特定的数值载荷。