PrometheUS:聊聊数据类型Histogram和Summary

简述

PrometheUS有四种数据类型Counter、Gauge、Histogram、Histogram。当我读官方文档的时候,前两种数据类型一读就明白了,可是后两种就让人难受了,怎么读也整不明白了,哎,头皮发麻呀,今天抽空折腾一下

Histogram

在有道翻译中这是柱状图的意思。举个栗子:我想获取北京最近十天内,温度分布情况,我们可以用Histogram这个数据类型,如果用图像表示,也就是柱形图比较合适了,如下图横轴是温度,竖轴是天数
在这里插入图片描述
当我们配置了Histogram数据类型后,我们能得到:

  • 每个桶中累积值的数量。这里的“桶”就是上面横轴的数值(5,10,15,20),而累计值不是上面的竖轴的值,而是一个累积计数,上图中5的桶对应的累积值是2,10的桶对应的累积值是4,15的桶对应的累积值对应的是8,20的桶对应的是10
  • 所有样本值的总和,比如上图中在形成柱状图之前,我们的数据应该是10天的温度(假设温度只在5,10,15,20中取值),然后统计出对应温度的天数而形成柱状图。此处的总和就是10天温度的总和
  • 样本数量,对应上图就是10了

Summary

这种类型类似于Histogram,他们都提供了样本值的总和和样本数量。但是Summary没有提供每个桶中的累积值,而是提供了一个 φ-quantiles。

  • φ-quantiles
    说一下 φ-quantiles吧。 φ-quantiles中的φ的取值范围是0 ≤ φ ≤ 1,总体的意思就是,如果你有N个样本值,首先要从小到大排序,然后取出排在φ *N的值。
  • histogram_quantile
    这是Histogram类型计算φ-quantiles时用的函数。这个函数的逻辑是,(1)最高的桶的上线如果不是+Inf,那么返回NaN (2)如果quantile 落在最高的桶,那么会返回最高桶的下线值 (3)如果最低桶的上限是大于0的,那么就会使用插值的方式。如果最低同的上限小于等于0,那么就会返回最低桶的上限
  • Quantile error
    我觉得可以翻译成误差,对于Histogram来说,比如我们有一个200ms 到 300ms的桶,我们的值都接近于220ms,所以0.95-quantiles应该接近于220ms,但是实际上,PrometheUS会使用插值的方法计算φ-quantiles,那么取值就会是295ms
    而对于Summary来说,上面的情况不会出现。但是Summary在定义φ-quantiles的时候,会定义一个波动范围,那么实际上φ-quantiles的计算会在φ加减波动范围内波动,如果这个范围内值的波动范围很大,那么取值就会不准确了

Summary和Histogram的不同

Histogram Summary
能获取到的值 可以获取到每个桶的累积值 能获取到φ-quantiles,但是φ是在客户端写死的,比如φ在客户端时0.5,那么通过API就只能获取0.5-quantiles
φ-quantiles的计算 需要在server端通过histogram_quantile()函数实现 客户端直接计算
客户端性能 优于Summary 因为要计算φ-quantiles,所以性能差了点
Quantile error避免方式 需要控制桶之间的间隔 需要控制φ的范围,在summary定义φ时会同时定一个波动范围,比如φ为0.95波动范围是0.01那么0.95-quantiles会在0.96-quantiles和0.94-quantiles取值
场景 如果你的φ-quantiles中φ不能定死,那么就要使用Histogram类型。如果你对要对一部分数据进行计算,那么要使用这种类型

实现

我用go写了个小demon:

  • 目录结构
    在这里插入图片描述
  • histogram.go
package histogram

import (
	"fmt"
	"github.com/prometheus/client_golang/prometheus"
)

var (
	TemperatureHistogram = prometheus.NewHistogram(prometheus.HistogramOpts{
		Name: "beijing_temperature",
		Help: "The temperature of the beijing",
		Buckets: prometheus.LinearBuckets(0,10,3),
	})
)

func InsertTemperature(){
	var temperature = [10]float64{1,4,5,10,14,15,20,25,11,30}
	for i:=0;i<len(temperature);i++{
		TemperatureHistogram.Observe(temperature[i])
		fmt.Printf("insert number: %f \n", temperature[i])
	}
}
  • summary
package summary

import (
	"fmt"
	"github.com/prometheus/client_golang/prometheus"
)

var (
	SalarySummary = prometheus.NewSummary(prometheus.SummaryOpts{
		Name: "beijing_salary",
		Help: "the relationship between salary and population of beijing city",
		Objectives: map[float64]float64{0.5:0.05,0.8:0.001,0.9:0.01,0.95:0.01},
	})
)

func InsertSummary(){
	var salary = [10]float64{8000,7000,8900,10000,9800,17000,15000,14000,11000,12000}
	for i:=0;i<len(salary);i++{
		SalarySummary.Observe(salary[i])
		fmt.Printf("Insert number: %f \n", salary[i])
	}
}
  • main.go
package main

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"test_histograms/src/histogram"
	"test_histograms/src/summary"

	"log"
	"net/http"
)

func init()  {
	prometheus.MustRegister(histogram.TemperatureHistogram)
	prometheus.MustRegister(summary.SalarySummary)
}

func main()  {
		histogram.InsertTemperature()
		summary.InsertSummary()
		http.Handle("/metrics", promhttp.Handler())
		log.Fatal(http.ListenAndServe(":8080",nil))
}

运行,访问测试

在这里插入图片描述


先写的这里了,如果有问题或者异议,请进QQ群630300475,大家聊聊

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章