浅谈prometheus client golang
含类型精讲+接口示例+源码节选
Prometheus:
prometheus是什么,网上已经有很多文章了,prometheus的部署和启动可以参照这个链接。prometheus为使用者提供了http接口,使用者可以使用PromQl通过get或post来从prometheus进行query。prometheus http api传送
示例:
命名规则
在https://github.com/prometheus/common/blob/master/model/metric.go定义了prometheus metric的命名规则,即只能为大小写字母,数字,’_’,’:’,并且名字不能为空string,其他的字符均不可出现
func IsValidMetricName(n LabelValue) bool {
if len(n) == 0 {
return false
}
for i, b := range n {
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == ':' || (b >= '0' && b <= '9' && i > 0)) {
return false
}
}
return true
}
Client golang四种类型:
counter
计数器,并且只能增长和重置。例如:一个网站的总访问量,机器的运行时长
gauge
测量值,或瞬时记录值,可以增加,也可以减少。例如:一个视频的同时观看人数,当前运行的进程数
histogram
- 直方图,一个histogram会生成三个指标,分别是_count,_sum,_bucket。暂时为了好理解,先把_sum指标理解为Gauge,然后_count指标就是对Gauge值修改的总次数,而_bucket指标分成了几个桶子,把每次修改的值放进桶子里,不过会把值分几个层次,进入不同的桶,每个桶子里面的个数,就是直方图的纵坐标(实际情况是这个桶之前所有桶里面的个数是这个桶的纵坐标),而桶子的划分条件,就是横坐标。
- 举个铁球做例子,我们一共有1000个大小不同的铁球,质量从1kg-100kg不等,假设我分5个桶,每个桶存储不同质量的铁球,第一个桶0-20kg,第二个20-40kg,后面依此。然后1000个铁球,就是histogram的count,而1000个铁球的总质量就是histogram的sum,那么bucket就是那五个桶,当然几个桶,桶的规则怎样都是可以设计的,这五个桶每个的0-20,20-40…就是横坐标,而每个桶中的个数,就是纵坐标。根据这些数据就可以形成一个直方图。
- 因为直方图能够分出数据的质量,所以应用直方图的例子如:页面的响应时间,一块业务代码的时延
- 一个不错的例子:传送门
- 刚接触的可能会懵懵的,不过不太复杂,建议多去实践一下。
summary
- 概要,summary和histogram类似也会产生三个指标,分别是_count,_sum,和{quantile} ,count和sum与histogram的概念相同,quantile的含义是分位数,我们都知道中位数,那么中位数其实就是一个五分quantile,而summary可以在定义时指定很多分位数,如五分数,九分数,九九分数。九分数的概念就是比这个数小的数占百分之九十。
- summary和histogram类似也可以用来描述页面响应时间这类型的值,但差别是,histogram可以很容易看出来长尾值,比如投票很多时候都是去掉一个最高分,去掉一个最低分这种,长尾值就是很影响平均数的值,所有直方图能够很容易分析出问题数据。 而summary更能发现百分之多少的页面响应时间是多少,更能分析出页面响应时间的总体情况。
比较
- summary和histogram都很容易看出平均数(即_sum/_count),但是histogram容易发现影响平均数的极端值,而histogram可以直接得到分位数,两种结构可以由开发者根据数据需求自行抉择。
- histogram由clinet go直接算出分位数,而summary虽然可以算出分位数,但是更多是由开发者计算,或者调用prometheus的api获取histogram的分位数,prometheus处理函数传送门。
四种类型的接口(go):
下面图片可传送:
Counter
counter.Inc(), counter.Add(123)
Gauge
gauge.Set(), gauge.Inc(), gauge.Dec(), gauge.Add(123) , gauge.Sub(321)
Histogram
histogram.Observer(123)//添加此数据到此histogram实例(使其观察)
Summary
共有接口
type Metric interface {
//获取此metric的描述
Desc() *Desc
//转化为proto格式的Metric,返回
Write(*dto.Metric) error //dto "github.com/prometheus/client_model/go"
}
四种类型使用:
client golang的代码均是安全的,使用了sync库下的读写锁和CAS原子操作
package main
//不是伪代码,可以直接go run
import (
"net/http"
"time"
"log"
"math"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
MyTestCounter = prometheus.NewCounter(prometheus.CounterOpts{
//因为Name不可以重复,所以建议规则为:"部门名_业务名_模块名_标量名_类型"
Name: "my_test_counter", //唯一id,不可重复Register(),可以Unregister()
Help: "my test counter", //对此Counter的描述
})
MyTestGauge = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "my_test_gauge",
Help: "my test gauge",
})
MyTestHistogram = prometheus.NewHistogram(prometheus.HistogramOpts{<