GOprometheus
Posted 一曲长歌一剑天涯
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GOprometheus相关的知识,希望对你有一定的参考价值。
参考资料
[1] prometheus包的使用
[2] Prometheus监控安装及使用
[3] Prometheus Client教程
[4] 使用 Prometheus 对 Go 应用程序进行监测
[5] 带你读《Prometheus监控实战》
[6] Prometheus
https://eddycjy.com/posts/pro...
https://yunlzheng.gitbook.io/...
1. 简介
prometheus包提供了用于实现监控代码的metric原型和用于注册metric的registry。子包(promhttp)允许通过HTTP来暴露注册的metric或将注册的metric推送到Pushgateway。
Metrics
prometheus一共有5种metric类型,前四种为:Counter,Gauge,Summary 和Histogram,每种类型都有对应的vector版本:GaugeVec, CounterVec, SummaryVec, HistogramVec,vector版本细化了prometheus数据模型,增加了label维度。第5种metric为Untyped,它的运作方式类似Gauge,区别在于它只向prometheus服务器发送类型信号。
只有基础metric类型实现了Metric接口,metric和它们的vector版本都实现了collector接口。collector负责一系列metrics的采集,但是为了方便,metric也可以“收集自己”。注意:Gauge, Counter, Summary, Histogram, 和Untyped自身就是接口,而GaugeVec, CounterVec, SummaryVec, HistogramVec, 和UntypedVec则不是接口。
为了创建metric和它们的vector版本,需要选择合适的opts结构体,如GaugeOpts, CounterOpts, SummaryOpts, HistogramOpts, 或UntypedOpts.
Custom Collectors and constant Metrics
实现自己的metric,一般只需要实现自己的collector即可。如果已经有了现成的metric(prometheus上下文之外创建的),则无需使用Metric类型接口,只需要在采集期间将现有的metric映射到prometheus metric即可,此时可以使用 NewConstMetric, NewConstHistogram, and NewConstSummary (以及对应的Must… 版本)来创建metric实例,以上操作在collect方法中实现。describe方法用于返回独立的Desc实例,NewDesc用于创建这些metric实例。(NewDesc用于创建prometheus识别的metric)
如果只需要调用一个函数来收集一个float值作为metric,那么推荐使用GaugeFunc, CounterFunc, 或UntypedFunc。
Advanced Uses of the Registry
MustRegister 是注册collector最通用的方式。如果需要捕获注册时产生的错误,可以使用Register 函数,该函数会返回错误。
如果注册的collector与已经注册的metric不兼容或不一致时就会返回错误。registry用于使收集的metric与prometheus数据模型保持一致。不一致的错误会在注册时而非采集时检测到。前者会在系统的启动时检测到,而后者只会在采集时发生(可能不会在首次采集时发生),这也是为什么collector和metric必须向Registry describe它们的原因。
以上提到的registry都被称为默认registry,可以在全局变量DefaultRegisterer中找到。使用NewRegistry可以创建custom registry,或者可以自己实现Registerer 或Gatherer接口。custom registry的Register和Unregister运作方式类似,默认registry则使用全局函数Register和Unregister。
custom registry的使用方式还有很多:可以使用NewPedanticRegistry来注册特殊的属性;可以避免由DefaultRegisterer限制的全局状态属性;也可以同时使用多个registry来暴露不同的metrics。
DefaultRegisterer注册了Go runtime metrics (通过NewGoCollector)和用于process metrics 的collector(通过NewProcessCollector)。通过custom registry可以自己决定注册的collector。
HTTP Exposition
Registry实现了Gather接口。调用Gather接口可以通过某种方式暴露采集的metric。通常metric endpoint使用http来暴露metric。通过http暴露metric的工具为promhttp子包。
函数和类型说明:
func Register(c Collector) error:使用DefaultRegisterer来注册传入的Collector
func Unregister(c Collector) bool:使用DefaultRegisterer来移除传入的Collector的注册信息
type AlreadyRegisteredError:该类型实现了error接口,由Register返回,用于判断用于注册的collector是否已经被注册过
type Collector:用于采集prometheus metric,如果运行多个相同的实例,则需要使用ConstLabels来注册这些实例。实现collector接口需要实现Describe和Collect方法,并注册collector。
type Registerer:负责collector的注册和去注册,实现custom registrer时应该实现该接口
// MustRegister implements Registerer.
func (r *Registry) MustRegister(cs ...Collector) {
for _, c := range cs {
if err := r.Register(c); err != nil {
panic(err)
}
}
}
2. 示例
https://blog.csdn.net/runner6...
https://www.cnblogs.com/FG123...
[1] 下载案例
git clone https://github.com/crockitwoo...
[2] 建立go.mod
$ cd go-prometheus-example
$ touch go.mod
键入以下内容:
module go-prometheus-example
go 1.12
$ go mod tidy
[3] 修改main.go
将"github.com/crockitwood/go-prometheus-example/monitor"改为"go-prometheus-example/monitor"
[4] 编译运行
$ go build
$ ./go-prometheus-example
[5] 访问网址
http://localhost:8080/hello
http://localhost:8080/query
http://localhost:8080/metrics
3. Prometheus 四大度量指标
- Counter (计数器)类型代表一个累积的指标数据,其单调递增,只增不减。在应用场景中,像是请求次数、错误数量等等,就非常适合用 Counter 来做指标类型,另外 Counter 类型,只有在被采集端重新启动时才会归零。
- Gauge (仪表盘)类型代表一个可以任意变化的指标数据,其可增可减。在应用场景中,像是 Go 应用程序运行时的 Goroutine 的数量就可以用该类型来表示,因为其是浮动的数值,并非固定的,侧重于反馈当前的情况。
Histogram(累计直方图) 类型将会在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等等),并将其计入可配置的存储桶(bucket)中,后续可通过指定区间筛选样本,也可以统计样本总数。 - Summary(摘要) 类型将会在一段时间范围内对数据进行采样,但是与 Histogram 类型不同的是 Summary 类型将会存储分位数(在客户端进行计算),而不像 Histogram 类型,根据所设置的区间情况统计存储。
Prometheus通过指标名称(metrics name)以及对应的一组标签(labelset)唯一定义一条时间序列。指标名称反映了监控样本的基本标识,而label则在这个基本特征上为采集到的数据提供了多种特征维度。用户可以基于这些特征维度过滤,聚合,统计从而产生新的计算后的一条时间序列。
4. 查询
func HandleGetQueryResp(c *gin.Context){
//queryString:="promhttp_metric_handler_requests_total"
//queryString:="cpu_total_info"
queryString:="cpu_total_info{}[5m]"
fmt.Println("queryString=",queryString)
// create prom client
newClient, err := api.NewClient(api.Config{Address: "http://localhost:9090"})
//newClient, err := api.NewClient(api.Config{Address: "http://localhost:10086/metrics"})
if nil != err {
fmt.Println("NewClient err=",err)
return
}
// create prom client http api
promAPI := v1.NewAPI(newClient)
// instant value, type is vector
resp, _, err := promAPI.Query(context.TODO(), queryString, time.Time{})
//resp, _,err := promAPI.LabelValues(context.TODO(), queryString,time.Time{},time.Time{})
if nil != err {
fmt.Println("Query err=",err)
return
}
cpuValue := resp.(model.Matrix)
fmt.Println("cpuValue=",cpuValue)
fmt.Println("len=",cpuValue.Len())
fmt.Println("cpuValue[0].Metric.String()=",cpuValue[0].Metric.String())
byts,err:=cpuValue[0].Values[0].Value.MarshalJSON()
fmt.Println("byts=",string(byts))
fmt.Println("cpuValue[0].Metric.Values=",cpuValue[0].Values)
zer:=cpuValue[0].Metric["cpu"]
fmt.Println("cpuValue[0].Metric[cpu]=",zer)
for a,b:= range cpuValue[0].Metric{
fmt.Println("a=",a)
fmt.Println("b=",b)
}
c.JSON(http.StatusOK, resp)
return
}
resp结果:
[{"metric":{
"__name__":"cpu_total_info",
"instance":"localhost:10086",
"job":"cpu",
"nice":"nice",
"user":"user"
},
"values":
[[1610368090.67,"1"], # 时间,值
[1610368300.67,"16"]]
}]
[
{
"metric":{
"__name__":"disk_info",
"disk_file_system":"general",
"disk_label":"free",
"disk_mount_point":"total",
"instance":"localhost:10086",
"job":"cpu","node_ip":"1.1.1.1"
},
"values":[
[1610419795.669,"22778143113216"],
[1610419900.669,"40493879795712"]
]
},
{
"metric":{
"__name__":"disk_info",
"disk_file_system":"general",
"disk_label":"total",
"disk_mount_point":"total",
"instance":"localhost:10086",
"job":"cpu","node_ip":"1.1.1.1"
},
"values":[
[1610419795.669,"63494033448960"],
[1610419900.669,"112878281687040"]
]
},
{
"metric":{
"__name__":"disk_info",
"disk_file_system":"general",
"disk_label":"used",
"disk_mount_point":"total",
"instance":"localhost:10086",
"job":"cpu","node_ip":"1.1.1.1"
},
"values":[
[1610419795.669,"40715890335744"],
[1610419900.669,"72384401891328"]
]
},
{
"metric":{
"__name__":"disk_info",
"disk_file_system":"general",
"disk_label":"used_rate",
"disk_mount_point":"total",
"instance":"localhost:10086",
"job":"cpu","node_ip":"1.1.1.1"
},
"values":[
[1610419795.669,"64.12553766721038"],
[1610419900.669,"64.12606642260637"]
]
}
]
以上是关于GOprometheus的主要内容,如果未能解决你的问题,请参考以下文章