3. 指标采集基础:Counter、Histogram、Gauge、UpDownCounter 的定义与使用场景

在 OpenTelemetry 指标体系中,Instrument(测量工具) 是数据采集的最小单元。不同的 Instrument 对应不同的语义模型,选错 Instrument 会导致监控数据失真或无法正确聚合。本章深入剖析四种核心 Instrument 的定义、行为特征与典型场景。

3.1 四种核心 Instrument 概览

Instrument 单调性 聚合方式 典型用途
Counter 单调递增(只增不减) Sum / Rate 请求总数、错误计数、写入行数
UpDownCounter 可增可减 Sum 活跃连接数、队列深度、库存量
Histogram 无单调性约束 分位数 / 桶计数 / Sum 请求延迟、响应大小、批处理耗时
Gauge 无单调性约束 LastValue / Min / Max CPU 使用率、内存占用、磁盘温度
选型口诀: 只增不减用 Counter,可增可减用 UpDownCounter,分布统计用 Histogram,瞬时快照用 Gauge。

3.2 Counter —— 单调递增计数器

定义: Counter 只允许 Add(positive) 操作,值永远单调递增。服务重启后归零重新计数。

核心行为:

  • 只能增加,不能减少,不能重置(除非进程重启)。
  • 后端自动聚合为 Sum 或 Rate(每秒增量)。
  • 适合统计“发生了多少次”的事件。

使用场景:

  • HTTP 请求总数
  • 数据库查询执行次数
  • 任务调度触发次数
  • 错误日志产生条数
// Go 示例:记录数据库查询次数
dbQueryCounter, _ := meter.Int64Counter(
    "db.queries.total",
    metric.WithDescription("Total number of database queries executed"),
)
dbQueryCounter.Add(ctx, 1, metric.WithAttributes(
    attribute.String("db.system", "postgresql"),
    attribute.String("db.operation", "SELECT"),
))

3.3 UpDownCounter —— 可增减计数器

定义: UpDownCounter 允许 Add(positive) 和 Add(negative),值可以在正负方向变化,但不会低于零(业务层可自行约束)。

核心行为:

  • 支持正负增量,后端聚合为 Sum。
  • 适合跟踪“当前存量”或“瞬时水位”。
  • 与 Gauge 的区别:UpDownCounter 强调累计变化量,Gauge 强调瞬时快照。

使用场景:

  • 数据库连接池活跃连接数
  • 消息队列待处理消息数
  • 任务调度器排队任务数
  • 内存池已分配块数
// Java 示例:跟踪连接池活跃连接
UpDownCounter activeConnections = meter
    .upDownCounterBuilder("db.connections.active")
    .setDescription("Current number of active database connections")
    .build();

// 建立连接时 +1
activeConnections.add(1);
// 释放连接时 -1
activeConnections.add(-1);
常见误区: 不要用 Counter 记录连接数。连接数会下降,Counter 无法表达下降语义。此时必须使用 UpDownCounter 或 Gauge。

3.4 Histogram —— 分布直方图

定义: Histogram 将观测值分配到预定义的桶(Bucket)中,记录每个桶的计数、所有值的总和以及观测次数。不保留原始数据点。

核心行为:

  • 必须指定桶边界(如 [0, 10, 50, 100, 500])。
  • 输出三个聚合指标:桶计数、总和、观测次数。
  • 后端可计算 p50、p90、p99 等分位数。

使用场景:

  • API 响应延迟分布
  • 数据库查询耗时分布
  • 批处理任务处理时间分布
  • 数据迁移单条记录处理耗时
# Python 示例:记录查询延迟分布
histogram = meter.create_histogram(
    name="db.query.duration",
    description="Histogram of database query duration in milliseconds",
    unit="ms",
    boundaries=[1, 5, 10, 25, 50, 100, 500, 1000],
)
histogram.record(42.5, {"db.operation": "INSERT"})

3.5 Gauge —— 瞬时快照

定义: Gauge 记录某个时间点的瞬时值,不关心历史变化趋势。通常由外部系统回调设置。

核心行为:

  • 使用 Set(value) 或 Record(value) 更新当前值。
  • 后端聚合为 LastValue,也可配置 Min / Max。
  • 不累积,不计算速率。

使用场景:

  • 当前 CPU 使用率
  • 当前内存占用字节数
  • 磁盘剩余空间百分比
  • 数据库连接池最大连接数配置
// C# 示例:记录当前内存使用量
var memoryGauge = meter.CreateObservableGauge(
    "process.memory.usage",
    () => new[] { new Measurement<long>(Process.GetCurrentProcess().WorkingSet64) }
);

3.6 Instrument 选型决策流程

决策树:

  1. 数据是否只增不减? → 是 → Counter
  2. 数据是否可增可减且需要累计总量? → 是 → UpDownCounter
  3. 是否需要分析分布特征(p50/p99)? → 是 → Histogram
  4. 以上都不符合,只需当前瞬时值? → Gauge
Instrument 选型决策流程 指标数据源 只增不减? Counter 需要分布特征? Histogram 可增可减? UpDownCounter Gauge 提示:Histogram 也可用于可增可减数据,但主要优势在分布分析;Gauge 是兜底方案,优先使用语义更明确的 Instrument

3.7 数据库迁移场景中的 Instrument 映射

在数据库迁移任务调度场景中,不同阶段需要不同的 Instrument 来精确刻画系统状态:

监控指标 推荐 Instrument 说明
迁移任务调度次数 Counter 每次调度触发 +1,只增不减
迁移失败次数 Counter 失败事件累积计数
当前排队任务数 UpDownCounter 任务入队 +1,出队 -1
单条记录迁移耗时 Histogram 分析 p50/p99 迁移延迟
源数据库 CPU 使用率 Gauge 瞬时快照,不累积
目标数据库连接池活跃数 UpDownCounter 连接建立/释放动态变化
最佳实践: 在数据库迁移任务中,优先使用 Histogram 记录迁移延迟,配合 Counter 记录总行数和失败行数,再使用 UpDownCounter 跟踪队列水位。三种 Instrument 组合即可覆盖 90% 的监控需求。