原文連接:一文搞懂 Prometheus 的直方圖html
Prometheus 中提供了四種指標類型(參考:Prometheus 的指標類型),其中直方圖(Histogram)和摘要(Summary)是最複雜和難以理解的,這篇文章就是爲了幫助你們加深對這 histogram
類型指標的理解。linux
根據上篇文檔,Histogram 會在一段時間範圍內對數據進行採樣(一般是請求持續時間或響應大小等),並將其計入可配置的存儲桶(bucket)中。但這句話仍是不太好理解,下面經過具體的示例來講明。git
假設咱們想監控某個應用在一段時間內的響應時間,最後監控到的樣本的響應時間範圍爲 0s~10s。如今咱們將樣本的值域劃分爲不一樣的區間,即不一樣的 bucket
,每一個 bucket 的寬度是 0.2s。那麼第一個 bucket 表示響應時間小於等於 0.2s 的請求數量,第二個 bucket 表示響應時間大於 0.2s 小於等於 0.4s 的請求數量,以此類推。github
Prometheus 的 histogram 是一種累積直方圖,與上面的區間劃分方式是有差異的,它的劃分方式以下:還假設每一個 bucket 的寬度是 0.2s,那麼第一個 bucket 表示響應時間小於等於 0.2s 的請求數量,第二個 bucket 表示響應時間小於等於 0.4s 的請求數量,以此類推。也就是說,每個 bucket 的樣本包含了以前全部 bucket 的樣本,因此叫累積直方圖。函數
上節內容告訴咱們,Prometheus 中的 histogram 是累積的,這是很奇怪的,由於一般狀況下非累積的直方圖更容易理解。Prometheus 爲何要這麼作呢?post
想象一下,若是 histogram 類型的指標中加入了額外的標籤,或者劃分了更多的 bucket,那麼樣本數據的分析就會變得愈來愈複雜。若是 histogram 是累積的,在抓取指標時就能夠根據須要丟棄某些 bucket,這樣能夠在下降 Prometheus 維護成本的同時,還能夠粗略計算樣本值的分位數。經過這種方法,用戶不須要修改應用代碼,即可以動態減小抓取到的樣本數量。.net
假設某個 histogram 類型指標的樣本數據以下:3d
如今咱們但願 Prometheus 在抓取指標時丟棄響應時間在 100ms
如下的 bucket,就能夠經過下面的 relabel 配置來實現:code
其中,example_latency_seconds_bucket
用來匹配標籤 __name__
的值,'0.0.*' 用來匹配標籤 le
的值,即 le
的值爲 0.0x
。而後將匹配到的樣本丟棄。htm
經過這種方法,你能夠丟棄任意的 bucket,但不能丟棄 le="+Inf"
的 bucket,由於 histogram_quantile
函數須要使用這個標籤。
另外 histogram 還提供了 _sum
指標和 _count
指標,即便你丟棄了全部的 bucket,仍然能夠經過這兩個指標值來計算請求的平均響應時間。
經過累積直方圖的方式,還能夠很輕鬆地計算某個 bucket 的樣本數佔全部樣本數的比例。例如,想知道響應時間小於等於 1s 的請求佔全部請求的比例,能夠經過如下公式來計算:
example_latency_seconds_bucket{le="1.0"} / ignoring (le) example_latency_seconds_bucket{le="+Inf"}
Prometheus 經過 histogram_quantile
函數來計算分位數(quantile),並且是一個預估值,並不徹底準確,由於這個函數是假定每一個區間內的樣本分佈是線性分佈來計算結果值的。預估的準確度取決於 bucket 區間劃分的粒度,粒度越大,準確度越低。如下圖爲例:
假設有 10000
個樣本,第 9501
個樣本落入了第 8 個 bucket。第 8 個 bucket 總共有 368
個樣本,其中第 9501
個樣本在該 bucket 中屬於第 93
個樣本。
根據 Prometheus 源代碼文件 promql/quantile.go 第 108 行的公式:
return bucketStart + (bucketEnd-bucketStart)*float64(rank/count)
咱們能夠計算(quantile=0.95)的樣本值爲:
這個值已經很接近精確的分位數值了。關於 histogram_quantile 函數的詳細使用方式,請參考:PromQL 內置函數。
本文主要介紹了 histogram 的工做原理以及分位數的計算方法,相信經過本文的拋磚引玉,你們應該對 Prometheus 的 histogram 有了更深一步的瞭解,下篇文章將會爲你們呈現 Summary 的工做方式。