4 prometheus包

Prometheus 的 client_golang 库中的 prometheus 包是用于实现监控指标定义、注册和暴露的核心模块。以下是其主要作用及常用函数的详细说明:

​主要作用​

  1. ​指标类型定义​​ 提供四大基础监控指标类型,满足不同监控场景需求:

    • ​Counter(计数器)​​:用于累计数值(如请求数、错误数),只增不减。

    • ​Gauge(仪表盘)​​:表示瞬时值,可增可减(如内存使用量、并发连接数)。

    • ​Histogram(直方图)​​:统计样本分布(如请求延迟),支持分桶计数。

    • ​Summary(摘要)​​:提供分位数计算(如 P99 延迟),适合单机统计。

  2. ​标签管理​​ 通过 *Vec 类型(如 CounterVec)支持多维度标签,实现灵活的数据分类。例如,按 HTTP 方法和状态码分类请求数。

  3. ​注册中心(Registry)​​ 管理指标的注册与生命周期,支持全局注册表(DefaultRegisterer)和自定义注册表,避免指标重复注册。

  4. ​自定义收集器(Collector)​​ 允许用户实现自定义指标采集逻辑,适用于集成第三方系统或复杂指标生成场景。

常量

Summary

const (
    DefMaxAge     = 10 * time.Minute  // 观测数据的默认有效期(10分钟)
    DefAgeBuckets = 5                 // 计算数据年龄的默认分桶数
    DefBufCap     = 500               // 收集观测值的默认缓冲区容量
)
  • ​用途​​: 这些常量用于配置 Summary 类型(摘要指标)的行为:

    • DefMaxAge:观测数据在内存中的保留时间,超过此时间的数据会被滚动淘汰。

    • DefAgeBuckets:用于按时间窗口分桶,计算观测数据的年龄分布(类似滑动窗口)。

    • DefBufCap:缓冲区大小,用于临时存储观测值,直到分位数计算完成。

  • ​设计意图​​: 平衡内存占用与计算精度。例如:

    • DefMaxAge=10分钟 表示只关注最近 10 分钟的数据分布。

    • DefBufCap=500 限制内存使用,防止高并发场景下的 OOM。

Histogram

  • ​用途​​: 配置直方图(Histogram)中“零值桶”的行为:

    • DefNativeHistogramZeroThreshold:默认零值阈值为 2^-128,用于定义“近似零值”的边界。所有绝对值小于此阈值的观测值会被归类到零值桶(le=0)。

    • NativeHistogramZeroThresholdZero=-1:表示创建一个“严格零值桶”,仅接收精确为零的观测值(如 0,而非 0.0000001)。

  • ​设计意图​​:

    • 通过 2^-128 确保零值桶在不同分辨率下的一致性(兼容 IEEE 754 浮点标准)。

    • 允许用户通过 NativeHistogramZeroThresholdZero 严格区分零与非零值(如统计零错误请求)。

标签

  • ​用途​​: 限制 Exemplar(附加在指标上的诊断信息,如 Trace ID)的标签长度,防止存储过大的标签数据。

  • ​设计意图​​: 在提供调试信息的同时,避免因标签过长导致性能问题。

变量

全局默认注册器与收集器

  • ​作用​​: 这两个全局变量用于管理指标的注册(Registerer)和收集(Gatherer),默认指向同一个 Registry 实例(defaultRegistry)。

  • ​预注册的收集器​​:

    • defaultRegistry 默认包含两个收集器:

      1. ​进程指标收集器​​(NewProcessCollector,仅 Linux 有效)。

      2. ​Go 运行时指标收集器​​(NewGoCollector,Go 1.9 之前版本可能引发 STW 停顿)。

  • ​注意事项​​:

    • 修改这些全局变量需谨慎,可能影响依赖它们的代码(如 promhttp.Handler())。

    • 若需避免全局状态,应使用自定义的 RegistererGatherer 实例。

直方图默认分桶

  • ​用途​​: Histogram 的默认分桶配置,适用于测量网络服务的响应时间(单位:秒)。

  • ​设计意图​​: 覆盖从 5 毫秒到 10 秒的典型延迟范围,但实际场景中通常需要自定义分桶(如微服务或高频交易场景)。

  • ​示例​​:

    • 若服务 99% 的响应时间 < 100ms,可缩小分桶范围以提高精度:

常用函数

​指标命名与标签处理​

​BuildFQName(namespace, subsystem, name string) string`​

  • ​作用​​:生成指标的​​完全限定名称​​(Fully Qualified Name),格式为 namespace_subsystem_name.

  • ​参数​​:

    • namespace:命名空间(如 http)。

    • subsystem:子系统(如 request)。

    • name:指标名(如 duration_seconds)。

  • ​示例​​:

  • ​注意​​:若任一参数为空,会自动省略下划线分隔符。

​MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair​

  • ​作用​​:将标签名和值组合成 Protobuf 格式的 LabelPair 结构,用于序列化指标数据。

  • ​参数​​:

    • desc:指标描述符(包含标签名)。

    • labelValues:标签值列表(顺序需与 desc 中的标签名一致)。

  • ​典型场景​​:在自定义 Collector 实现中构造指标标签。

​直方图分桶生成​

​LinearBuckets(start, width float64, count int) []float64

  • ​作用​​:生成​​线性增长​​的分桶边界。

  • ​参数​​:

    • start:第一个桶的上边界。

    • width:桶宽(每个桶比前一个增加 width)。

    • count:桶总数。

  • ​示例​​:

ExponentialBuckets(start, factor float64, count int) []float64​

  • ​作用​​:生成​​指数增长​​的分桶边界。

  • ​参数​​:

    • start:第一个桶的上边界。

    • factor:增长因子(每个桶是前一个的 factor 倍)。

    • count:桶总数。

  • ​示例​​:

ExponentialBucketsRange(minBucket, maxBucket float64, count int) []float64

  • ​作用​​:生成在 [minBucket, maxBucket] 范围内​​指数分布​​的分桶。

  • ​参数​​:

    • minBucket:最小桶边界(>0)。

    • maxBucket:最大桶边界。

    • count:桶总数(≥2)。

  • ​示例​​:

​指标收集器(Collector)管理​

Register(c Collector) error

  • ​作用​​:向 DefaultRegisterer 注册一个指标收集器。

  • ​返回值​​:若收集器已注册或标签冲突,返回错误。

  • ​示例​​:

MustRegister(cs ...Collector)

  • ​作用​​:批量注册收集器,若失败则 panic

  • ​典型用法​​:在程序初始化时注册全局收集器。

​Unregister(c Collector) bool

  • ​作用​​:从 DefaultRegisterer 注销收集器。

  • ​返回值​​:是否成功注销。

  • ​场景​​:动态卸载插件或模块的指标。

​​DescribeByCollect(c Collector, descs chan<- *Desc)​​

  • ​作用​​:辅助函数,通过调用 Collect 方法自动生成指标的 Desc 描述。

  • ​用途​​:简化自定义 Collector 的实现,避免手动定义 Describe 方法。

  • ​示例​​:

​工具函数​

​NewPidFileFn(pidFilePath string) func() (int, error)

  • ​作用​​:生成一个函数,用于读取指定 PID 文件并返回进程 ID。

  • ​场景​​:监控守护进程时,确认进程是否存活。

  • ​示例​​:

WriteToTextfile(filename string, g Gatherer) error

  • ​作用​​:将指标数据写入文本文件,格式符合 Prometheus 的 textfile 规范。

  • ​用途​​:供 node_exportertextfile 收集器采集自定义指标。

  • ​示例​​:

类型

Counter

  • 类型定义:

Counter 是一个 Metric,它表示一个只会上升的数值。这意味着它不能用于计算数量也可以减少的项目。统计请求总数、错误数、任务完成数等。

func NewCounter(opts CounterOpts) Counter

  • 作用:根据提供的 CounterOpt 创建一个新的Counter。

CounterVec

  • 类型定义

CounterVec 是一个 Collector,它捆绑了一组 Counter,这些 Counter 都共享相同的 Desc,但其变量标签具有不同的值。如果你想计算按各种维度分区的同一事物(例如,按响应代码和方法分区的 HTTP 请求数量),则使用此方法。使用 NewCounterVec 创建实例。

  • CounterVec 内部使用 metricVec 结构​​,通过 sync.Map 管理标签组合到 Counter 的映射

  • ​标签组合的哈希​​:每个标签键值对会被编码为唯一的哈希值,用于快速查找对应的 Counter。 ​

  • WithLabelValues()With() 方法是线程安全的​​,但频繁调用可能导致锁竞争。

  • ​优化建议​​:预先获取常用标签组合的 Counter 对象,避免重复计算哈希。

func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec

  • 作用:NewCounterVec 根据提供的 CounterOpt 创建一个新的 CounterVec,并按给定的标签名称进行分区。

func (v *CounterVec) WithLabelValues(lvs ...string) Counter

  • 作用:按标签值的顺序获取对应的 Counter

  • 错误处理:在遇到错误时触发panic

func (v *CounterVec) With(labels Labels) Counter

  • 作用:通过 Labels 对象指定标签键值对,返回对应的Counter

  • 错误处理:在遇到错误时触发panic

Gauge

  • 类型定义

Gauge 表示一个可以任意上升和下降的数值。Gauge 通常用于温度或当前内存使用等测量值,但也用于可以上下波动的 “计数”,例如正在运行的 goroutine 的数量。

func NewGauge(opts GaugeOpts) Gauge

  • 作用:根据 GaugeOpts 创建一个Gauge对象

返回的实现针对快速 Set 方法进行了优化。如果可以选择通过 Set 而不是 Inc/Dec/Add/Sub 来管理 Gauge 的值,请选择前者。例如,返回的 Gauge 的 Inc 方法比 NewCounter 返回的 Counter 的 Inc 方法慢。这与仪表和计数器的典型情况相匹配,前者往往是 Set 密集型,后者是 Inc 密集型的。

GaugeVec

  • 类型定义:

func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec

  • 作用:NewGaugeVec 根据提供的 GaugeOpts 创建一个新的 GaugeVec,并按给定的标签名称进行分区。

WithLabelValue/With方法跟CounterVec类型一致。

Histogram

  • 类型定义

Histogram​ 用于记录观测值的分布(如请求延迟、响应大小),并将数据分配到预定义的桶(Buckets)中,支持后续计算分位数(如 P90、P99)。

与 Summary 的 Observe 方法相比,Histogram 的 Observe 方法具有非常低的性能开销。

Observe方法:

  • 负值可能干扰计数器重置检测(仅影响普通 Histogram,Native Histogram 已修复)。

  • 实验性 Native Histograms 需 Prometheus v2.40+ 并启用特性标志。

​Native Histograms(实验性)​

  • 动态稀疏桶,解决传统 Histogram 需预定义桶的问题。

  • 启用方式:在 HistogramOpts 中配置 NativeHistogramBucketFactor

  • 版本要求:Prometheus 服务端版本 ≥2.40。

func NewHistogram(opts HistogramOpts) Histogram

  • 作用:NewHistogram 根据提供的 HistogramOpts 创建新的 Histogram。如果 HistogramOpts 中的存储桶没有严格按递增顺序排列,它会 panic。

  • ​常用预设桶​​:

    • DefBuckets:默认的指数增长桶(适用于秒级延迟:[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10])。

    • LinearBuckets(start, width float64, count int):线性递增桶。

    • ExponentialBuckets(start, factor float64, count int):指数递增桶。

HistogramVec

  • 作用:HistogramVec 是一个 Collector,它捆绑了一组直方图,这些直方图都共享相同的描述,但其变量标签具有不同的值。如果您想对按各种维度分区的同一事物进行计数(例如 HTTP 请求延迟,按状态代码和方法分区),则使用此方法。使用 NewHistogramVec 创建实例。

func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec

  • 作用:NewHistogramVec 根据提供的 HistogramOpts 创建一个新的 HistogramVec,并按给定的标签名称进行分区。

HistogramOpts

  • 类型定义:

字段名
类型
默认值
是否必填
描述
注意事项

​Namespace​

string

空字符串

指标命名空间,用于分类管理(如 myapp

SubsystemName 组合成指标全名(格式:Namespace_Subsystem_Name

​Subsystem​

string

空字符串

指标子系统,进一步细分命名空间(如 http

同上

​Name​

string

​是​

指标名称(如 request_duration_seconds

必须非空且符合 Prometheus 命名规则(仅允许 [a-zA-Z0-9_]

​Help​

string

空字符串

指标的帮助信息

相同名称的指标必须拥有相同的 Help 字符串

​ConstLabels​

Labels

nil

固定标签(如 {"env": "prod"}

避免高基数标签;禁止使用 quantile

​Buckets​

[]float64

DefBuckets(预设桶列表)

定义直方图的桶边界(如 []float64{0.1, 0.5, 1}

桶值必须严格递增;若为空则使用默认桶(若启用原生直方图则默认桶为空)

​NativeHistogramBucketFactor​

float64

1.0

稀疏桶的指数增长因子(≥1.0 启用原生直方图)

推荐值 1.1(平衡精度与性能);仅 Prometheus ≥2.40 支持

​NativeHistogramZeroThreshold​

float64

DefNativeHistogramZeroThreshold

绝对值小于此阈值的观测值计入“零桶”

建议设为 2 的幂次方(如 0.001);设为负数时仅精确零值计入零桶

​NativeHistogramMaxBucketNumber​

uint32

0

稀疏桶的最大数量限制(防止内存溢出)

生产环境建议设置合理值(如 1000);设为 0 表示无限制

​NativeHistogramMinResetDuration​

time.Duration

0

触发桶重置的最小时间间隔(超限时重置直方图)

若设为 10m,则每 10 分钟检查一次重置条件

​NativeHistogramMaxZeroThreshold​

float64

0

自动调整零阈值的上限值

用于动态平衡桶数量;需配合 MaxBucketNumber 使用

​NativeHistogramMaxExemplars​

int

10

原生直方图保留的样本(Exemplar)最大数量

设为 -1 禁用原生样本;样本用于关联跟踪数据(如 TraceID)

​NativeHistogramExemplarTTL​

time.Duration

5 分钟

样本的存活时间(超时自动删除)

设为负值则优先删除最旧样本

关键字段详解​

  1. ​Buckets​

  • ​默认桶​​:DefBuckets = []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10}

  • ​自定义示例​​:

  1. ​NativeHistogramBucketFactor​

  • ​稀疏桶特性​​:

    • 桶宽按指数增长,覆盖全范围浮点数(如 1.1 表示桶宽增长 10%)。

    • ​适用场景​​:高动态范围数据(如延迟从毫秒到小时)。

  1. ​NativeHistogramZeroThreshold​

  • ​示例​​:

  1. ​NativeHistogramMaxBucketNumber​

  • ​动态调整策略​​:

    1. 若桶数超限且超过 MinResetDuration,重置直方图。

    2. 否则增大零阈值或降低分辨率(桶宽翻倍)。

  1. ​NativeHistogramExemplarTTL​

  • ​示例​​:

  • 整体代码示例:

*Func

CounterFunc 是 Prometheus 客户端库提供的一种特殊计数器类型,允许通过 ​​回调函数​​ 动态获取计数器的值。与普通 Counter 不同,CounterFunc 的值由用户定义的函数在每次指标被抓取时计算,无需手动调用 Inc()Add()

​类型​

​语义​

​典型场景​

CounterFunc

单调递增的累计值

总任务处理量(需外部系统提供值)

GaugeFunc

可任意变化的瞬时值

当前内存使用量、活跃连接数

注意事项:

  1. ​单调性要求​​:

    • CounterFunc 的值 ​​理论上应单调递增​​(符合计数器的语义)。

    • 若值可能减少(如当前连接数),应改用 GaugeFunc

  2. ​性能优化​​:

    • 回调函数应 ​​快速执行​​,避免阻塞指标抓取。

    • 复杂计算或 I/O 操作建议异步更新并缓存结果。

  3. ​错误处理​​:

    • 回调函数中抛出 panic 会导致整个指标抓取失败,需自行处理异常。

  4. ​注册与注销​​:

    • 使用 MustRegister 注册后,若回调函数依赖外部资源,需在资源释放后调用 Unregister

Summary

  • Summary​ 用于记录观测值的滑动窗口分位数(如 P99 延迟),在​​客户端实时计算分位数​​,适合单实例的精确统计。

  • ​核心特性​​:

    • 在客户端计算分位数,无需服务端聚合。

    • 适用于需要实时分位数的场景(如监控单服务的接口延迟)。

    • ​不支持跨实例聚合​​(不同实例的分位数无法合并)。

​特性​

Summary

Histogram

​分位数计算位置​

客户端(实时计算)

服务端(通过 PromQL 聚合)

​适用场景​

单实例精确分位数

跨实例全局分位数

​资源消耗​

高(需维护滑动窗口数据)

低(预分桶,内存固定)

​分位数精度​

高(实时计算)

依赖分桶配置(可能有误差)

  • 类型定义:

func NewSummary(opts SummaryOpts) Summary

  • 作用:NewSummary 根据提供的 SummaryOpts 创建新的 Summary。

MaxAge作用机制:

  1. ​滑动窗口模型​

    • Summary 维护一个​​时间滑动窗口​​,仅保留最近 MaxAge 时间段内的观测数据。

    • 例如,若 MaxAge: 5 * time.Minute,则只有过去 5 分钟内的观测值会被保留并用于计算分位数。

  2. ​数据清理​

    • 客户端库会​​周期性检查并清理过期数据​​(默认每 1 分钟清理一次)。

    • 超过 MaxAge 的旧数据会被移除,释放内存。

  3. ​分位数计算​

    • 清理后,分位数(如 P99)仅基于窗口内剩余的数据计算。

    • 如果窗口内无数据,分位数指标(如 quantile="0.99")可能暂时消失或显示为 NaN

注意事项:

  1. ​数据清理是渐进的​

    • 清理操作不是实时触发,而是周期性执行(默认每分钟一次)。

    • 极端情况下,数据可能在过期后最多延迟 1 分钟才被删除。

  2. ​短 MaxAge 的影响​

    • MaxAge 过短(如 1 分钟),可能导致分位数波动较大(数据样本少)。

    • 适用于需要快速反映最新状态的场景(如实时监控)。

  3. ​长 MaxAge 的影响​

    • MaxAge 过长(如 1 小时),内存占用会持续增长。

    • 适用于需要长期趋势分析的场景(需权衡资源消耗)。

SummaryVec

  • 作用:SummaryVec 是一个 Collector,它捆绑了一组 Summation,这些 Summaries 都共享相同的 Desc,但其变量标签具有不同的值。如果您想对按各种维度分区的同一事物进行计数(例如 HTTP 请求延迟,按状态代码和方法分区),则使用此方法。使用 NewSummaryVec 创建实例。

func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec

  • 作用:NewSummaryVec 根据提供的 SummaryOpts 创建一个新的 SummaryVec,并按给定的标签名称进行分区。

  • 注意:“quantile”是一个非法的标签名称。如果使用此标签名称,NewSummaryVec 将 panic。

CurryWith(labels Labels) (ObserverVec, error)​

  • ​作用​​:​​部分绑定标签​​,生成一个预设部分标签的新 SummaryVec

  • ​参数​​:labels Labels:预设的标签键值对(如 Labels{"method": "GET"})。

  • ​返回值​​:

    • ObserverVec:新生成的 SummaryVec,仅需提供剩余标签。

    • error:标签未定义或键不匹配时返回错误。

MustCurryWith(labels Labels) ObserverVec​

  • ​作用​​:与 CurryWith 类似,但出错时直接触发 panic,简化代码。

  • ​参数​​:labels Labels:预设的标签键值对。

  • ​返回值​​:ObserverVec

With(labels Labels) Observer

  • ​作用​​:通过标签键值对直接获取 Observer,​​不返回错误​​(若标签无效会触发 panic)。

  • ​参数​​:labels Labels:完整的标签键值对。

  • ​返回值​​:Observer

WithLabelValues(lvs ...string) Observer​

  • ​作用​​:通过标签值列表直接获取 Observer,​​不返回错误​​(若标签值无效会触发 panic)。

  • ​参数​​:lvs ...string:标签值列表,​​顺序必须严格匹配定义时的标签顺序​​。

  • ​返回值​​:Observer

​方法​

​核心作用​

​错误处理​

​适用场景​

NewSummaryVec

创建带标签的 SummaryVec

初始化多维分位数监控指标

CurryWith

部分绑定标签

返回 error

减少重复标签配置

GetMetricWith

安全获取带标签的 Summary

返回 error

需要错误处理的动态标签场景

GetMetricWithLabelValues

安全通过标签值获取 Summary

返回 error

需要错误处理的固定标签顺序场景

MustCurryWith

部分绑定标签(简化版)

panic

已知标签合法的场景

With

直接获取带标签的 Summary。跟GetMetricWith类似

panic

快速操作已知合法的标签键值对

WithLabelValues

直接通过标签值获取 Summary。跟GetMetricWithLabelValues类似

panic

快速操作已知合法的标签值顺序

SummaryOpts

  • 类型定义:

字段名
类型
默认值
是否必填
描述
注意事项

​Namespace​

string

空字符串

指标命名空间,用于分类管理(如 myapp

SubsystemName 共同组成指标全名(格式:Namespace_Subsystem_Name

​Subsystem​

string

空字符串

指标子系统,进一步细分命名空间(如 http

同上

​Name​

string

​是​

指标名称(如 request_duration_seconds

必须非空且符合 Prometheus 指标命名规则(仅允许 [a-zA-Z0-9_]

​Help​

string

空字符串

指标的帮助信息,用于描述指标用途

相同名称的指标必须拥有相同的 Help 字符串

​ConstLabels​

prometheus.Labels

nil

固定标签(如 {"env": "prod"}

禁止使用 quantile 作为标签名;避免高基数标签

​Objectives​

map[float64]float64

map

分位数目标及允许误差(如 {0.5: 0.05} 表示中位数误差 ±5%)

默认值将在 v1.0.0 变更为空,建议显式设置;误差值越小,资源消耗越大

​MaxAge​

time.Duration

DefMaxAge(通常 10 分钟)

观测值的有效时间窗口(旧数据过期后被丢弃)

仅影响分位数计算;必须为正数

​AgeBuckets​

uint32

DefAgeBuckets(通常 5)

时间窗口内的分段数量(用于管理 MaxAge 内的数据分布)

值越大,内存消耗越高;设为 1 时窗口过期后分位数完全重置

​BufCap​

uint32

DefBufCap(通常 500)

采样数据流的缓冲区容量

建议设置为 500 的倍数(如 1000);高吞吐场景可增大此值

​​字段关键点总结​:

  1. ​必填字段​​:仅 Name 必须设置。

  2. ​名称规则​​:

    • 全名格式:Namespace_Subsystem_Name(如 myapp_http_request_duration_seconds)。

    • 名称需符合正则表达式 ^[a-zA-Z_][a-zA-Z0-9_]*$

  3. ​分位数配置​​:

    • 若不设置 Objectives,则不会生成分位数指标(仅有 _count_sum)。

    • 示例:Objectives: map[float64]float64{0.9: 0.01} 表示计算 P90,误差不超过 ±1%。

  4. ​性能调优​​:

    • MaxAgeAgeBuckets:平衡分位数精度与内存开销。

    • BufCap:影响高吞吐场景下的观测值缓冲能力。​

Opts

Opts 是用于创建各类指标(如 Counter、Gauge、Histogram)的通用配置选项。不同指标类型(如 CounterOptsGaugeOpts)本质上是 Opts 的别名或扩展。

字段名​

​类型​

​是否必填​

​默认值​

​说明​

​示例​

​注意事项​

Namespace

string

""

指标命名空间,用于组织指标层级。

"order_service"

SubsystemName 共同组成全限定名(如 order_service_http_requests_total)。

Subsystem

string

""

指标子系统,进一步细化分类。

"http"

通常按功能模块划分(如 httpdatabase)。

Name

string

​是​

-

指标核心名称,需符合 Prometheus 命名规范(仅允许 [a-zA-Z0-9_])。

"requests_total"

必须非空,否则注册时报错。

Help

string

​强烈建议​

""

指标的帮助信息,描述其用途。相同名称的指标必须拥有相同的 Help

"Total HTTP requests processed."

未设置可能导致监控数据难以理解。

ConstLabels

Labels

nil

固定标签,为所有指标实例添加静态元信息(如环境、版本)。

Labels{"env": "prod", "version": "v1.2.0"}

避免动态值(如用户 ID),防止时间序列基数爆炸。

  1. ​全限定名生成规则​

    • 格式为 <Namespace>_<Subsystem>_<Name>,缺失部分自动省略。

    • 示例:

  2. ​命名规范​

    • 仅允许字母、数字和下划线(_),如 http_requests_total

    • 错误示例:http-requests-total(包含短横线)。

  3. ConstLabels 的替代方案​

    • 动态标签应通过 *Vec 类型(如 CounterVecGaugeVec)管理,而非 ConstLabels

    • 固定元信息(如 env="prod")适合用 ConstLabels

Labels

Labels 是一个键值对集合,用于表示 Prometheus 指标的标签(Metadata),其类型定义为:

  • ​键(Label Name)​​:标识标签的维度(如 methodstatus_code)。

  • ​值(Label Value)​​:对应维度的具体取值(如 GET200)。

Registerer 接口​​/Registry类型

Registerer​ 是用于注册和管理指标收集器(Collector)的接口。Registry 是其默认实现,负责管理指标的生命周期。

核心方法​​

​方法​

​说明​

Register(Collector) error

注册一个 Collector,若名称冲突或标签不一致返回错误。

MustRegister(...Collector)

批量注册 Collector,失败时触发 panic

Unregister(Collector) bool

注销一个 Collector,返回是否成功。

Registry​ 是 Registerer 的具体实现,用于管理多个 Collector 的注册和指标收集。

创建方法

​函数​

​说明​

NewRegistry() *Registry

创建标准 Registry,仅检查指标名称和标签冲突。

NewPedanticRegistry() *Registry

创建严格模式 Registry,额外检查 Help 字符串和类型一致性(适合测试)。

核心方法

​方法​

​说明​

Gather() ([]*dto.MetricFamily, error)

收集所有注册的指标数据,转换为 Protobuf 格式(用于 HTTP 暴露或自定义处理)。

Collect(chan<- Metric)

实现 Collector 接口,收集所有指标到通道中。

Describe(chan<- *Desc)

实现 Collector 接口,描述所有注册的指标。

​示例​​:暴露指标到 HTTP 服务

包装 Registerer​​

通过包装现有 Registerer,可以全局修改注册的指标名称或标签。

​WrapRegistererWith(labels, reg)

  • ​作用​​:为所有注册的指标添加 ​​固定标签​​。

  • ​参数​​:

    • labels Labels:需要添加的标签键值对。

    • reg Registerer:被包装的原始 Registerer

  • ​示例​​:

WrapRegistererWithPrefix(prefix, reg)​​

  • ​作用​​:为所有注册的指标名称添加 ​​前缀​​。

  • ​参数​​:

    • prefix string:名称前缀(如 myapp_)。

    • reg Registerer:被包装的原始 Registerer

  • ​示例​​:

​使用场景​

​​默认注册表​​

  • ​直接使用全局注册表​​:

​​自定义注册表​​

  • ​隔离指标​​:不同模块使用独立的 Registry,避免名称冲突。

​​添加全局标签​​

  • ​统一标记环境信息​​:

​​指标聚合与暴露​​

  • ​自定义 HTTP 端点​​:

​方法详解​

​Register(c Collector) error

  • ​作用​​:注册一个 Collector,失败返回错误(如名称冲突)。

  • ​示例​​:

​MustRegister(cs ...Collector)

  • ​作用​​:批量注册 Collector,失败时 panic

  • ​示例​​:

​Unregister(c Collector) bool

  • ​作用​​:注销已注册的 Collector,返回是否成功。

  • ​示例​​:

Gather() ([]*dto.MetricFamily, error)

  • ​作用​​:收集所有指标数据,转换为 Protobuf 格式。

  • ​用途​​:自定义指标处理或导出到其他系统。

  • ​示例​​:

​场景​

​推荐方法​

​全局默认监控​

使用 prometheus.DefaultRegistererprometheus.MustRegister

​模块化指标隔离​

为每个模块创建独立的 Registry

​添加环境标签​

使用 WrapRegistererWith 包装默认 Registry。

​严格指标检查(测试环境)​

使用 NewPedanticRegistry()

​动态注销指标(如插件)​

结合 RegisterUnregister 管理 Collector 生命周期。

​注意事项​​

  1. ​避免重复注册​​:同一 Collector 不可重复注册到同一 Registry。

  2. ​高基数标签​​:避免在 WrapRegistererWith 中使用动态值(如用户 ID)。

  3. ​线程安全​​:RegistryRegister/Unregister 方法需在并发环境中加锁。

  4. ​性能影响​​:频繁调用 Gather() 可能影响性能,建议与 HTTP 暴露间隔结合使用。

为什么要注册到不同的Registry

  1. ​​指标隔离与模块化​​

  • ​场景​​:不同模块(如微服务、插件、中间件)需要独立管理自己的指标。

  • ​优势​​:

    • ​避免命名冲突​​:不同模块的同名指标(如 http_requests_total)可以隔离在不同 Registry 中。

    • ​独立生命周期​​:模块卸载时,直接销毁对应的 Registry,无需遍历全局 Registry 删除指标。

  • ​示例​​:

​2. ​​定制化指标暴露​​

  • ​场景​​:将不同模块的指标暴露到独立的 HTTP 端点。

  • ​优势​​:

    • ​按需暴露​​:敏感指标(如调试接口)可绑定到特定端口,不与业务指标混用。

    • ​权限隔离​​:不同端口的指标可配置不同的访问权限。

  • ​示例​​:

​​3. ​​动态配置与灵活性​​

  • ​场景​​:动态加载/卸载插件或功能模块。

  • ​优势​​:

    • ​热更新​​:插件启用时注册到独立 Registry,禁用时直接销毁,无需重启服务。

    • ​资源节省​​:避免全局 Registry 残留未使用的指标描述符(Desc)。

  • ​示例​​:

​​4. ​​性能优化​​

  • ​场景​​:高频更新或大规模指标的监控场景。

  • ​优势​​:

    • ​减少锁竞争​​:全局 Registry 的 Register/Gather 使用互斥锁,独立 Registry 可降低锁粒度。

    • ​并行收集​​:多个 Registry 的 Gather() 可并发执行,提升指标收集效率。

  • ​示例​​:

​5. ​​测试与调试​​

  • ​场景​​:单元测试或集成测试中验证特定模块的指标。

  • ​优势​​:

    • ​精准断言​​:测试时仅关注目标 Registry 的指标,排除其他模块干扰。

    • ​严格模式​​:使用 NewPedanticRegistry() 在测试中检查指标规范(如 Help 描述是否为空)。

  • ​示例​​:

​6. ​​多租户与多环境支持​​

  • ​场景​​:同一服务需要为不同租户或环境(如开发、生产)生成隔离的指标。

  • ​优势​​:

    • ​标签隔离​​:通过不同 Registry 为指标添加租户/环境专属标签(如 tenant_id="user1")。

    • ​数据分离​​:避免跨租户的指标混合导致查询复杂度上升。

  • ​示例​​:

​​总结:何时使用多个 Registry​

​场景​

​推荐方案​

模块化服务开发

每个模块使用独立 Registry

动态插件机制

插件生命周期绑定到独立 Registry

多租户/多环境监控

为每个租户创建专属 Registry

高频指标收集

分离高负载模块到独立 Registry

严格测试

使用 NewPedanticRegistry()

通过合理使用多 Registry,可实现监控系统的​​高内聚、低耦合​​,提升可维护性和性能。

自定义指标

Desc

Desc(描述符)是用于定义指标元数据的关键类型。它包含指标的名称、帮助信息、标签(动态标签和固定标签),确保指标在注册和数据收集时的一致性。

核心作用

  • 元数据封装​​:存储指标名称(fqName)、帮助信息(help)、动态标签(variableLabels)和固定标签(constLabels)。

  • ​唯一性标识​​:通过名称和标签组合唯一标识指标。

  • ​校验规则​​:同一注册表中的同名指标必须满足一致性和唯一性。

类型定义

  • ​Fully Qualified Name (fqName)​​:指标的完整名称(如 http_requests_total)。

  • ​Help​​:指标的描述信息(如 Total HTTP requests)。

  • ​Variable Labels​​:动态标签(每次记录指标时可变化,如 method, status_code)。

  • ​Constant Labels​​:固定标签(创建时确定,如 app="myapp")。

func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc

  • 作用:创建 Desc 实例

  • fqName​:

    • 必须非空,且符合命名规范(仅允许 [a-zA-Z0-9_])。

    • 示例:http_requests_total(正确)、http-requests-total(错误,含连字符)。

  • help​:

    • 同一全名的指标必须使用相同的 help

  • variableLabels​:

    • 动态标签名列表(如 []string{"method"}),标签值在记录指标时动态指定。

  • constLabels​:

    • 固定标签键值对(如 prometheus.Labels{"app": "web"}),在创建 Desc 时确定。

一致性和唯一性规则​​

  • ​同名指标必须一致​​:

    • 若两个 DescfqName 相同,则 helpvariableLabelsconstLabels 的键名必须一致。

    • ​错误示例​​:

      • 注册时会报错:inconsistent help strings for metric

  • ​固定标签值必须不同​​:

    • 同名 DescconstLabels 值需不同以区分不同指标。

    • ​正确示例​​:

func NewInvalidDesc(err error) *Desc

NewInvalidDesc 是一个用于错误处理的关键函数。它允许开发者创建带有错误信息的无效指标描述符(Desc),从而在注册收集器时明确报告问题。

核心作用

  • ​错误传递​​:将初始化阶段的错误传递给 Prometheus 注册机制。

  • ​提前失败​​:在注册收集器时(而非运行时)暴露问题,避免后续数据收集出现不可控错误。

注意事项

  1. 错误传播机制​​

  • ​注册阶段失败​​:调用 prometheus.Register() 时会检查 Describe 方法返回的 Desc。若存在无效描述符,注册立即失败。

  • 错误信息可见性​​:错误信息会通过注册函数的返回值暴露,需确保日志或监控系统捕获这些错误。

  1. 避免滥用​​

  • 不可恢复错误​​:仅在确实无法继续运行时使用(如关键配置缺失)。对于可重试错误(如临时网络故障),应通过重试逻辑处理。

  • 替代方案​​:若需标记指标为“不可用”,可返回一个带有特殊标签的指标(如 status="error"),而非中断收集器。

func (d *Desc) String() string

  • 作用:返回 Desc 的字符串表示,用于调试。

代码示例

Metric

Metric 是 Prometheus 监控指标的具体实例,它包含以下核心信息:

  • ​指标名称​​(如 http_requests_total)。

  • ​指标类型​​(Counter、Gauge、Histogram、Summary 等)。

  • ​标签​​(动态标签和固定标签)。

  • ​当前值​​(或分布数据)。

  • ​元数据​​(时间戳、Exemplars 等)。

创建普通指标:NewConstMetric 和 MustNewConstMetric​

  • 作用:创建计数器或仪表盘指标。

  • 函数定义如下:

参数​​:

  • desc *Desc:指标描述符。

  • valueType ValueTypeCounterValue(计数器)或 GaugeValue(仪表盘)。

  • value float64:指标当前值。

  • labelValues ...string:动态标签值(需与 DescvariableLabels 顺序一致)。

创建直方图:NewConstHistogram 和 MustNewConstHistogram​

  • ​功能​​:创建直方图指标,记录数据分布(如请求延迟)。

  • 函数定义如下:

  • ​参数​​:

    • count uint64:样本总数。

    • sum float64:所有样本值的总和。

    • buckets map[float64]uint64:各桶的累计计数(如 {0.5: 3} 表示 ≤0.5 的样本有 3 个)。

创建摘要:NewConstSummary 和 MustNewConstSummary​​

  • ​功能​​:创建摘要指标,记录分位数(如 P99 延迟)。

  • 函数定义如下:

  • ​参数​​:

    • quantiles map[float64]float64:分位数值(如 {0.5: 0.1} 表示 P50 为 0.1 秒)。

带时间戳的指标:NewConstMetricWithCreatedTimestamp

  • ​功能​​:为指标添加创建时间戳(通常用于标记指标生成时间)。

  • 函数定义如下:

  • ​参数​​:

    • ct time.Time:指标创建时间。

带时间戳和普通不带时间戳有什么区别

TSDB时间戳:

  • ​普通指标​​(不带显式时间戳)的时间戳由 Prometheus 在 ​​抓取时刻​​ 自动生成。

  • ​TSDB 存储的时间​​:每个样本(Sample)的时间戳是 Prometheus 拉取(Scrape)该指标的时间,而非指标实际产生的时间。

显式时间戳:

  • 当指标自带时间戳时,​​覆盖了 Prometheus 的默认抓取时间戳​​。这种设计是为了解决以下场景的痛点:

    • 处理历史数据或延迟数据​:应用需要上报 ​​过去某个时刻​​ 产生的指标(如离线批处理作业、延迟上报的监控事件)。

    • 高精度时间对齐​:需要将多个来源的指标按 ​​精确时间对齐​​(如分布式系统中的事件溯源)。

    • 避免抓取间隔导致的误差​​:应用的指标生成频率远高于 Prometheus 抓取间隔(如高频计数器)。

注意事项:

  • ​时间戳范围​​:

    • Prometheus 拒绝处理 ​​未来时间​​ 的样本(超过当前服务器时间 + 5 分钟)。

    • 样本时间戳不能 ​​过于陈旧​​(早于当前服务器时间 - 1 小时,具体取决于 --storage.tsdb.retention.time 配置)。

  • ​重复时间戳​​:同一时间序列(相同的指标名和标签)在相同时间戳下,只有最后一个样本会被保留。

什么时候使用显式时间戳

​场景​

​是否使用显式时间戳​

​说明​

实时监控(默认抓取)

Prometheus 自动管理时间戳

批处理作业上报历史数据

确保数据反映实际事件时间

高频数据上报(配合 Pushgateway)

避免抓取间隔导致的数据丢失

跨系统时间对齐

强制多个系统的数据在相同时间戳下对齐

错误处理:NewInvalidMetric

  • ​功能​​:创建带错误信息的无效指标(如配置错误时)。

  • 函数定义如下

MetricVec

MetricVec 是 Prometheus 客户端库中用于管理 ​​多标签组合指标集合​​ 的核心类型。它适用于需要根据动态标签值(如 HTTP 方法、状态码等)生成和管理多个指标的场景。

NewMetricVec

  • ​功能​​:创建 MetricVec 实例。

  • 函数定义如下:

  • ​参数​​:

    • desc *Desc:指标描述符(名称、帮助信息、标签等)。

    • newMetric func(lvs ...string) Metric:用于生成单个指标的函数。

GetMetricWith 和 GetMetricWithLabelValues​

  • ​功能​​:根据标签获取或创建指标实例。

    • GetMetricWith:通过 ​​标签键值对​​(Labels)获取指标。

    • GetMetricWithLabelValues:通过 ​​标签值列表​​(按顺序)获取指标。

  • ​参数​​:

    • labels Labels:标签键值对(如 Labels{"method": "GET", "status": "200"})。

    • lvs ...string:标签值列表(如 "GET", "200")。

  • ​示例​​:

  • ​注意​​:

    • GetMetricWithLabelValues 必须严格按照 variableLabels 的顺序提供标签值。

    • 若标签组合不存在,会自动创建新指标实例。

Delete 和 DeleteLabelValues

  • 功能​​:删除指定标签组合的指标实例。

    • Delete:根据 ​​标签键值对​​ 删除。

    • DeleteLabelValues:根据 ​​标签值列表​​ 删除。

  • ​示例​​:

DeletePartialMatch

  • 功能​​:根据 ​​部分标签匹配​​ 删除指标实例。

  • ​参数​​:

    • labels Labels:部分标签键值对(如 Labels{"method": "GET"})。

  • ​示例​​:

CurryWith

  • 功能​​:固定部分标签值,生成一个新的 MetricVec

  • ​用途​​:简化标签管理(如固定环境标签 env="prod")。

  • ​示例​​:

Reset

  • ​功能​​:清空所有指标实例。

  • ​用途​​:重置状态(如单元测试或服务重启时)。

  • ​示例​​:

示例

Colletcor

  • 一个 Collector 可以同时收集多个指标​​。Prometheus 的设计允许在一个 Collector 中聚合多个相关指标,这在需要逻辑分组或共享数据源时非常有用。

  • 类型定义:

方法名​

​参数名​

​参数类型​

​作用​

Describe

ch

chan<- *Desc

传递指标的 ​​描述符​​(Descriptor),用于注册时检查指标的唯一性和一致性。

Collect

ch

chan<- Metric

传递实际的 ​​指标数据​​(Metric),用于收集当前时刻的指标值。

  1. Describe 方法​

    • ​通道内容​​:发送 *Desc 类型指针,描述指标的元信息(名称、帮助文档、标签等)。

    • ​一致性检查​​:Prometheus 在注册时通过此方法验证指标是否冲突或重复。

    • ​示例​​:

  2. Collect 方法​

    • ​通道内容​​:发送 Metric 接口实现的具体指标数据(如 Gauge, Counter 等)。

    • ​实时收集​​:每次调用 Gather() 或 HTTP 暴露指标时触发此方法,生成当前时刻的指标值。

    • ​示例​​:

  3. ​单一指标 Collector​​(如 Gauge, Counter

  1. ​复合指标 Collector​​(如 GaugeVec, HistogramVec

​注意事项​​

​场景​

​处理方式​

​高并发调用​

DescribeCollect 需实现为 ​​线程安全​​(如加锁或无状态)。

​指标动态生成​

Collect 中实时生成指标(如从外部系统读取数据),避免在 Describe 中生成。

​错误处理​

Describe 执行失败,需发送 NewInvalidDesc() 到通道通知 Registry。

通过实现 Collector 接口,可以灵活扩展自定义指标(如集成第三方系统数据),并纳入 Prometheus 的统一管理中。

CollectorFunc

CollectorFunc 是 Prometheus 客户端库提供的一种 ​​函数适配器类型​​,用于将普通函数转换为符合 Collector 接口的对象。通过它,开发者可以快速实现自定义指标收集逻辑,无需定义结构体和实现 Describe/Collect 方法。

Describe 方法​​

  • ​功能​​:向 Prometheus 注册表声明指标描述符(Desc)。

  • ​默认行为​​:若未显式实现,Describe 方法不会发送任何 Desc,可能导致注册时报错。

  • ​重要规则​​:每个指标必须通过 Describe 方法声明其 Desc,否则 Prometheus 会认为指标元数据不一致。

​Collect 方法​​

  • ​功能​​:生成具体的指标数据(Metric)并发送到通道。

  • ​实现方式​​:直接调用 CollectorFunc 函数本身。

示例

最后更新于