4 prometheus包
Prometheus 的 client_golang 库中的 prometheus 包是用于实现监控指标定义、注册和暴露的核心模块。以下是其主要作用及常用函数的详细说明:
主要作用
指标类型定义 提供四大基础监控指标类型,满足不同监控场景需求:
Counter(计数器):用于累计数值(如请求数、错误数),只增不减。
Gauge(仪表盘):表示瞬时值,可增可减(如内存使用量、并发连接数)。
Histogram(直方图):统计样本分布(如请求延迟),支持分桶计数。
Summary(摘要):提供分位数计算(如 P99 延迟),适合单机统计。
标签管理 通过
*Vec类型(如CounterVec)支持多维度标签,实现灵活的数据分类。例如,按 HTTP 方法和状态码分类请求数。注册中心(Registry) 管理指标的注册与生命周期,支持全局注册表(
DefaultRegisterer)和自定义注册表,避免指标重复注册。自定义收集器(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默认包含两个收集器:进程指标收集器(
NewProcessCollector,仅 Linux 有效)。Go 运行时指标收集器(
NewGoCollector,Go 1.9 之前版本可能引发 STW 停顿)。
注意事项:
修改这些全局变量需谨慎,可能影响依赖它们的代码(如
promhttp.Handler())。若需避免全局状态,应使用自定义的
Registerer和Gatherer实例。
直方图默认分桶
用途:
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_exporter的textfile收集器采集自定义指标。示例:
类型
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)
与 Subsystem、Name 组合成指标全名(格式: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 分钟
否
样本的存活时间(超时自动删除)
设为负值则优先删除最旧样本
关键字段详解
Buckets
默认桶:
DefBuckets = []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10}自定义示例:
NativeHistogramBucketFactor
稀疏桶特性:
桶宽按指数增长,覆盖全范围浮点数(如
1.1表示桶宽增长 10%)。适用场景:高动态范围数据(如延迟从毫秒到小时)。
NativeHistogramZeroThreshold
示例:
NativeHistogramMaxBucketNumber
动态调整策略:
若桶数超限且超过
MinResetDuration,重置直方图。否则增大零阈值或降低分辨率(桶宽翻倍)。
NativeHistogramExemplarTTL
示例:
整体代码示例:
*Func
CounterFunc 是 Prometheus 客户端库提供的一种特殊计数器类型,允许通过 回调函数 动态获取计数器的值。与普通 Counter 不同,CounterFunc 的值由用户定义的函数在每次指标被抓取时计算,无需手动调用 Inc() 或 Add()。
类型
语义
典型场景
CounterFunc
单调递增的累计值
总任务处理量(需外部系统提供值)
GaugeFunc
可任意变化的瞬时值
当前内存使用量、活跃连接数
注意事项:
单调性要求:
CounterFunc的值 理论上应单调递增(符合计数器的语义)。若值可能减少(如当前连接数),应改用
GaugeFunc。
性能优化:
回调函数应 快速执行,避免阻塞指标抓取。
复杂计算或 I/O 操作建议异步更新并缓存结果。
错误处理:
回调函数中抛出 panic 会导致整个指标抓取失败,需自行处理异常。
注册与注销:
使用
MustRegister注册后,若回调函数依赖外部资源,需在资源释放后调用Unregister。
Summary
Summary 用于记录观测值的滑动窗口分位数(如 P99 延迟),在客户端实时计算分位数,适合单实例的精确统计。核心特性:
在客户端计算分位数,无需服务端聚合。
适用于需要实时分位数的场景(如监控单服务的接口延迟)。
不支持跨实例聚合(不同实例的分位数无法合并)。
特性
Summary
Histogram
分位数计算位置
客户端(实时计算)
服务端(通过 PromQL 聚合)
适用场景
单实例精确分位数
跨实例全局分位数
资源消耗
高(需维护滑动窗口数据)
低(预分桶,内存固定)
分位数精度
高(实时计算)
依赖分桶配置(可能有误差)
类型定义:
func NewSummary(opts SummaryOpts) Summary
作用:NewSummary 根据提供的 SummaryOpts 创建新的 Summary。
MaxAge作用机制:
滑动窗口模型
Summary维护一个时间滑动窗口,仅保留最近MaxAge时间段内的观测数据。例如,若
MaxAge: 5 * time.Minute,则只有过去 5 分钟内的观测值会被保留并用于计算分位数。
数据清理
客户端库会周期性检查并清理过期数据(默认每 1 分钟清理一次)。
超过
MaxAge的旧数据会被移除,释放内存。
分位数计算
清理后,分位数(如 P99)仅基于窗口内剩余的数据计算。
如果窗口内无数据,分位数指标(如
quantile="0.99")可能暂时消失或显示为NaN。
注意事项:
数据清理是渐进的
清理操作不是实时触发,而是周期性执行(默认每分钟一次)。
极端情况下,数据可能在过期后最多延迟 1 分钟才被删除。
短 MaxAge 的影响
若
MaxAge过短(如 1 分钟),可能导致分位数波动较大(数据样本少)。适用于需要快速反映最新状态的场景(如实时监控)。
长 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)
与 Subsystem、Name 共同组成指标全名(格式: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);高吞吐场景可增大此值
字段关键点总结:
必填字段:仅
Name必须设置。名称规则:
全名格式:
Namespace_Subsystem_Name(如myapp_http_request_duration_seconds)。名称需符合正则表达式
^[a-zA-Z_][a-zA-Z0-9_]*$。
分位数配置:
若不设置
Objectives,则不会生成分位数指标(仅有_count和_sum)。示例:
Objectives: map[float64]float64{0.9: 0.01}表示计算 P90,误差不超过 ±1%。
性能调优:
MaxAge和AgeBuckets:平衡分位数精度与内存开销。BufCap:影响高吞吐场景下的观测值缓冲能力。
Opts
Opts 是用于创建各类指标(如 Counter、Gauge、Histogram)的通用配置选项。不同指标类型(如 CounterOpts、GaugeOpts)本质上是 Opts 的别名或扩展。
字段名
类型
是否必填
默认值
说明
示例
注意事项
Namespace
string
否
""
指标命名空间,用于组织指标层级。
"order_service"
与 Subsystem 和 Name 共同组成全限定名(如 order_service_http_requests_total)。
Subsystem
string
否
""
指标子系统,进一步细化分类。
"http"
通常按功能模块划分(如 http、database)。
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),防止时间序列基数爆炸。
全限定名生成规则
格式为
<Namespace>_<Subsystem>_<Name>,缺失部分自动省略。示例:
命名规范
仅允许字母、数字和下划线(
_),如http_requests_total。错误示例:
http-requests-total(包含短横线)。
ConstLabels的替代方案动态标签应通过
*Vec类型(如CounterVec、GaugeVec)管理,而非ConstLabels。固定元信息(如
env="prod")适合用ConstLabels。
Labels
Labels 是一个键值对集合,用于表示 Prometheus 指标的标签(Metadata),其类型定义为:
键(Label Name):标识标签的维度(如
method、status_code)。值(Label Value):对应维度的具体取值(如
GET、200)。
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.DefaultRegisterer 和 prometheus.MustRegister。
模块化指标隔离
为每个模块创建独立的 Registry。
添加环境标签
使用 WrapRegistererWith 包装默认 Registry。
严格指标检查(测试环境)
使用 NewPedanticRegistry()。
动态注销指标(如插件)
结合 Register 和 Unregister 管理 Collector 生命周期。
注意事项
避免重复注册:同一
Collector不可重复注册到同一 Registry。高基数标签:避免在
WrapRegistererWith中使用动态值(如用户 ID)。线程安全:
Registry的Register/Unregister方法需在并发环境中加锁。性能影响:频繁调用
Gather()可能影响性能,建议与 HTTP 暴露间隔结合使用。
为什么要注册到不同的Registry
指标隔离与模块化
场景:不同模块(如微服务、插件、中间件)需要独立管理自己的指标。
优势:
避免命名冲突:不同模块的同名指标(如
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时确定。
一致性和唯一性规则
同名指标必须一致:
若两个
Desc的fqName相同,则help、variableLabels和constLabels的键名必须一致。错误示例:
注册时会报错:
inconsistent help strings for metric。
固定标签值必须不同:
同名
Desc的constLabels值需不同以区分不同指标。正确示例:
func NewInvalidDesc(err error) *Desc
NewInvalidDesc 是一个用于错误处理的关键函数。它允许开发者创建带有错误信息的无效指标描述符(Desc),从而在注册收集器时明确报告问题。
核心作用
错误传递:将初始化阶段的错误传递给 Prometheus 注册机制。
提前失败:在注册收集器时(而非运行时)暴露问题,避免后续数据收集出现不可控错误。
注意事项
错误传播机制
注册阶段失败:调用 prometheus.Register() 时会检查 Describe 方法返回的 Desc。若存在无效描述符,注册立即失败。
错误信息可见性:错误信息会通过注册函数的返回值暴露,需确保日志或监控系统捕获这些错误。
避免滥用
不可恢复错误:仅在确实无法继续运行时使用(如关键配置缺失)。对于可重试错误(如临时网络故障),应通过重试逻辑处理。
替代方案:若需标记指标为“不可用”,可返回一个带有特殊标签的指标(如 status="error"),而非中断收集器。
func (d *Desc) String() string
作用:返回
Desc的字符串表示,用于调试。
代码示例
Metric
Metric 是 Prometheus 监控指标的具体实例,它包含以下核心信息:
指标名称(如
http_requests_total)。指标类型(Counter、Gauge、Histogram、Summary 等)。
标签(动态标签和固定标签)。
当前值(或分布数据)。
元数据(时间戳、Exemplars 等)。
创建普通指标:NewConstMetric 和 MustNewConstMetric
作用:创建计数器或仪表盘指标。
函数定义如下:
参数:
desc *Desc:指标描述符。valueType ValueType:CounterValue(计数器)或GaugeValue(仪表盘)。value float64:指标当前值。labelValues ...string:动态标签值(需与Desc的variableLabels顺序一致)。
创建直方图: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),用于收集当前时刻的指标值。
Describe方法通道内容:发送
*Desc类型指针,描述指标的元信息(名称、帮助文档、标签等)。一致性检查:Prometheus 在注册时通过此方法验证指标是否冲突或重复。
示例:
Collect方法通道内容:发送
Metric接口实现的具体指标数据(如Gauge,Counter等)。实时收集:每次调用
Gather()或 HTTP 暴露指标时触发此方法,生成当前时刻的指标值。示例:
单一指标 Collector(如
Gauge,Counter)
复合指标 Collector(如
GaugeVec,HistogramVec)
注意事项
场景
处理方式
高并发调用
Describe 和 Collect 需实现为 线程安全(如加锁或无状态)。
指标动态生成
在 Collect 中实时生成指标(如从外部系统读取数据),避免在 Describe 中生成。
错误处理
若 Describe 执行失败,需发送 NewInvalidDesc() 到通道通知 Registry。
通过实现 Collector 接口,可以灵活扩展自定义指标(如集成第三方系统数据),并纳入 Prometheus 的统一管理中。
CollectorFunc
CollectorFunc 是 Prometheus 客户端库提供的一种 函数适配器类型,用于将普通函数转换为符合 Collector 接口的对象。通过它,开发者可以快速实现自定义指标收集逻辑,无需定义结构体和实现 Describe/Collect 方法。
Describe 方法
功能:向 Prometheus 注册表声明指标描述符(
Desc)。默认行为:若未显式实现,
Describe方法不会发送任何Desc,可能导致注册时报错。重要规则:每个指标必须通过
Describe方法声明其Desc,否则 Prometheus 会认为指标元数据不一致。
Collect 方法
功能:生成具体的指标数据(
Metric)并发送到通道。实现方式:直接调用
CollectorFunc函数本身。
示例
最后更新于