1. 课程导论:为什么需要自定义指标?OpenTelemetry 指标体系概览

1.1 为什么标准指标不够用?

在可观测性实践中,OpenTelemetry 提供了丰富的自动插桩(Auto-Instrumentation)能力,能够捕获 HTTP 请求量、数据库调用耗时、gRPC 错误率等通用指标。然而,业务逻辑的独特性决定了标准指标无法覆盖所有场景:

  • 业务语义缺失:标准指标只能告诉你“请求数”,无法区分“支付成功”与“支付失败”。
  • 维度不足:自动埋点通常只包含 HTTP 方法、状态码等通用标签,缺少 user_tier、region、product_id 等业务维度。
  • 聚合粒度不匹配:标准 Histogram 的桶(Bucket)分布面向通用延迟,无法针对特定 SLA(如 99 分位 < 200ms)优化。
  • 无法表达业务状态:队列积压长度、并发在线用户数、库存水位等瞬时值,标准指标无法直接提供。
核心结论:自定义指标是连接基础设施可观测性与业务可观测性的桥梁。没有自定义指标,你只能看到“系统在运行”,却看不到“业务在发生什么”。

1.2 OpenTelemetry 指标体系概览

OpenTelemetry 定义了四种基础指标类型(Metric Kind),每种类型对应不同的语义和聚合行为。理解它们的差异是设计自定义指标口径的第一步。

指标类型 英文名称 语义 典型场景 聚合方式
Counter Counter 单调递增的累计值 请求总数、错误总数、订单创建数 Sum / Rate
UpDownCounter UpDownCounter 可增可减的有符号累计值 活跃连接数、队列长度、库存余量 Sum / Delta
Histogram Histogram 数值分布采样,按桶统计 请求延迟、响应体大小、批处理耗时 分位数 / 桶计数 / Sum
Gauge Gauge 可上可下的瞬时快照值 CPU 使用率、内存占用、当前温度 LastValue / Min / Max
记忆口诀:Counter 只增不减,UpDownCounter 可增可减,Histogram 看分布,Gauge 看快照。

1.3 四种指标类型的核心区别

选择错误的指标类型会导致数据失真或查询困难。以下从三个关键维度对比:

  • 单调性:Counter 强制单调递增,UpDownCounter 和 Gauge 允许双向变化。
  • 聚合语义:Counter 和 UpDownCounter 适合做 Sum 聚合;Histogram 适合做分位数估算;Gauge 适合做 LastValue 展示。
  • 导出行为:Counter 在 Prometheus 中通常配合 rate() 使用;Histogram 自带 _bucket、_count、_sum 后缀;Gauge 直接暴露当前值。
// 伪代码示例:四种指标的定义差异
// Counter:只允许 Add(正数)
counter.Add(1, attribute.String("status", "success"))

// UpDownCounter:允许 Add(正数或负数)
upDownCounter.Add(1)   // 连接建立
upDownCounter.Add(-1)  // 连接关闭

// Histogram:记录单个观测值
histogram.Record(152.3, attribute.String("endpoint", "/checkout"))

// Gauge:设置当前值
gauge.Set(42.0, attribute.String("pool", "worker"))

1.4 指标类型选择决策树

下面这张 SVG 图帮助你快速判断应该使用哪种指标类型:

指标类型选择决策树 你的指标描述什么? 累计值(累计计数) 瞬时值(快照) 只增不减 可增可减 需要分布统计? Histogram Gauge Counter UpDownCounter 决策要点 • 先问“累计还是瞬时?” → 再问“只增不减还是可增可减?” → 最后问“需要分布吗?” • 90% 的业务指标落在 Counter 和 Histogram 上,Gauge 和 UpDownCounter 用于特殊场景

1.5 自定义指标的设计原则

在开始编码之前,记住三条黄金法则:

  1. 口径先行:先定义指标的名称、类型、单位、标签集合,再写代码。口径文档比代码更持久。
  2. 标签有界:避免使用 user_id、request_id 等无限基数(Cardinality)的标签,否则会导致存储爆炸和查询性能崩溃。
  3. 语义一致:同一业务含义的指标,在不同服务中保持相同的命名和标签结构。例如“订单创建数”统一使用 orders.created,不要一个服务用 order_create_count,另一个用 create_order_total。
常见陷阱:不要将 Histogram 当作 Gauge 使用。例如用 Histogram 记录“当前队列长度”是错误的,因为 Histogram 记录的是观测值的分布,而不是瞬时状态。队列长度应该使用 UpDownCounter 或 Gauge。

1.6 本章小结