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,大家聊聊

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