Prometheus 的客戶端庫中提供了四種核心的指標類型。但這些類型只是在客戶端庫(客戶端可以根據不同的數據類型調用不同的 API 接口)和在線協議中,實際在 Prometheus server 中並不對指標類型進行區分,而是簡單地把這些指標統一視為無類型的時間序列
2.1、Counter (計數器)
Counter 類型代表一種樣本數據單調遞增的指標,即只增不減,除非監控系統發生了重置。
例如,你可以使用 counter 類型的指標來表示服務的請求數、已完成的任務數、錯誤發生的次數等。counter 主要有兩個方法:
//將counter值加1.
Inc()
// 將指定值加到counter值上,如果指定值<0 會panic.
Add(float64)
Counter 類型數據可以讓用戶方便的了解事件產生的速率的變化,在 PromQL 內置的相關操作函數可以提供相應的分析,比如以 HTTP 應用請求量來進行說明:
//通過rate()函數獲取HTTP請求量的增長率
rate(http_requests_total[5m])
//查詢當前系統中,訪問量前10的HTTP地址
topk(10, http_requests_total)
不要將 counter 類型應用於樣本數據非單調遞增的指標,例如:當前運行的進程數量(應該用 Guage 類型)。
2.2、Guage( 儀表盤)
Guage 類型代表一種樣本數據可以任意變化的指標,即可增可減。guage 通常用於像溫度或者內存使用率這種指標數據,也可以表示能隨時增加或減少的“總數”,例如:當前並發請求的數量。
對於 Gauge 類型的監控指標,通過 PromQL 內置函數 [delta()]可以獲取樣本在一段時間內的變化情況,例如,計算 CPU 溫度在兩小時內的差異:
dalta(cpu_temp_celsius{host="zeus"}[2h])
你還可以通過PromQL 內置函數 [predict_linear()]基於簡單線性回歸的方式,對樣本數據的變化趨勢做出預測。例如,基於 2 小時的樣本數據,來預測主機可用磁盤空間在 4 個小時之后的剩余情況:
predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0
2.3、 Histogram(直方圖)
在大多數情況下人們都傾向於使用某些量化指標的平均值,例如 CPU 的平均使用率、頁面的平均響應時間。這種方式的問題很明顯,以系統 API 調用的平均響應時間為例:如果大多數 API 請求都維持在 100ms 的響應時間范圍內,而個別請求的響應時間需要 5s,那么就會導致某些 WEB 頁面的響應時間落到中位數的情況,而這種現象被稱為長尾問題。
為了區分是平均的慢還是長尾的慢,最簡單的方式就是按照請求延遲的范圍進行分組。例如,統計延遲在 0~10ms 之間的請求數有多少而 10~20ms 之間的請求數又有多少。通過這種方式可以快速分析系統慢的原因。Histogram 和 Summary 都是為了能夠解決這樣問題的存在,通過 Histogram 和 Summary 類型的監控指標,我們可以快速了解監控樣本的分布情況。
Histogram 在一段時間范圍內對數據進行采樣(通常是請求持續時間或響應大小等),並將其計入可配置的存儲桶(bucket)中,后續可通過指定區間篩選樣本,也可以統計樣本總數,最后一般將數據展示為直方圖。
Histogram 類型的樣本會提供三種指標(假設指標名稱為 <basename>
):
-
樣本的值分布在 bucket 中的數量,命名為
<basename>_bucket{le="<上邊界>"}
。解釋的更通俗易懂一點,這個值表示指標值小於等於上邊界的所有樣本數量。 -
// 在總共2次請求當中。http 請求響應時間 <=0.005 秒 的請求次數為0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.005",} 0.0 // 在總共2次請求當中。http 請求響應時間 <=0.01 秒 的請求次數為0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.01",} 0.0 // 在總共2次請求當中。http 請求響應時間 <=0.025 秒 的請求次數為0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.025",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.05",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.075",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.1",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.25",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.5",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="0.75",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="1.0",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="2.5",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="5.0",} 0.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="7.5",} 2.0 // 在總共2次請求當中。http 請求響應時間 <=10 秒 的請求次數為 2 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="10.0",} 2.0 io_namespace_http_requests_latency_seconds_histogram_bucket{path="/",method="GET",code="200",le="+Inf",} 2.0
-
所有樣本值的大小總和,命名為
<basename>_sum
。// 實際含義: 發生的2次 http 請求總的響應時間為 13.107670803000001 秒 io_namespace_http_requests_latency_seconds_histogram_sum{path="/",method="GET",code="200",} 13.107670803000001
-
樣本總數,命名為
<basename>_count
。值和<basename>_bucket{le="+Inf"}
相同。// 實際含義: 當前一共發生了 2 次 http 請求 io_namespace_http_requests_latency_seconds_histogram_count{path="/",method="GET",code="200",} 2.0
注意
bucket 可以理解為是對數據指標值域的一個划分,划分的依據應該基於數據值的分布。注意后面的采樣點是包含前面的采樣點的,假設
xxx_bucket{...,le="0.01"}
的值為 10,而xxx_bucket{...,le="0.05"}
的值為 30,那么意味着這 30 個采樣點中,有 10 個是小於 10 ms 的,其余 20 個采樣點的響應時間是介於 10 ms 和 50 ms 之間的。
可以通過 histogram_quantile() 函數來計算 Histogram 類型樣本的分位數。分位數可能不太好理解,你可以理解為分割數據的點。我舉個例子,假設樣本的 9 分位數(quantile=0.9)的值為 x,即表示小於 x 的采樣值的數量占總體采樣值的 90%。Histogram 還可以用來計算應用性能指標值(Apdex score)。
2.4、Summary(摘要)
與 Histogram 類型類似,用於表示一段時間內的數據采樣結果(通常是請求持續時間或響應大小等),但它直接存儲了分位數(通過客戶端計算,然后展示出來),而不是通過區間來計算。
Summary 類型的樣本也會提供三種指標(假設指標名稱為 ):
-
樣本值的分位數分布情況,命名為
<basename>{quantile="<φ>"}
。// 含義:這 12 次 http 請求中有 50% 的請求響應時間是 3.052404983s io_namespace_http_requests_latency_seconds_summary{path="/",method="GET",code="200",quantile="0.5",} 3.052404983 // 含義:這 12 次 http 請求中有 90% 的請求響應時間是 8.003261666s io_namespace_http_requests_latency_seconds_summary{path="/",method="GET",code="200",quantile="0.9",} 8.003261666
-
所有樣本值的大小總和,命名為
<basename>_sum
。// 含義:這12次 http 請求的總響應時間為 51.029495508s io_namespace_http_requests_latency_seconds_summary_sum{path="/",method="GET",code="200",} 51.029495508
-
樣本總數,命名為
<basename>_count
。// 含義:當前一共發生了 12 次 http 請求 io_namespace_http_requests_latency_seconds_summary_count{path="/",method="GET",code="200",} 12.0
現在可以總結一下 Histogram 與 Summary 的異同:
- 它們都包含了
<basename>_sum
和<basename>_count
指標 - Histogram 需要通過
<basename>_bucket
來計算分位數,而 Summary 則直接存儲了分位數的值。
關於 Summary 與 Histogram 的詳細用法,請參考 histograms and summaries。
不同語言關於 Summary 的客戶端庫使用文檔:
三、數據模型
Prometheus 所有采集的監控數據均以指標(metric)的形式保存在內置的時間序列數據庫當中(TSDB):屬於同一指標名稱,同一標簽集合的、有時間戳標記的數據流。除了存儲的時間序列,Prometheus 還可以根據查詢請求產生臨時的、衍生的時間序列作為返回結果。
3.1、指標名稱和標簽
每一條時間序列由指標名稱(Metrics Name)以及一組標簽(鍵值對)唯一標識。其中指標的名稱(metric name)可以反映被監控樣本的含義(例如,http_requests_total
— 表示當前系統接收到的 HTTP 請求總量),指標名稱只能由 ASCII 字符、數字、下划線以及冒號組成,同時必須匹配正則表達式 [a-zA-Z_:][a-zA-Z0-9_:]*
。
(時間序列[唯一標識])=指標名稱+標簽)
注意:
冒號用來表示用戶自定義的記錄規則,不能在 exporter 中或監控對象直接暴露的指標中使用冒號來定義指標名稱。
通過使用標簽,Prometheus 開啟了強大的多維數據模型:對於相同的指標名稱,通過不同標簽列表的集合,會形成特定的度量維度實例(例如:所有包含度量名稱為 /api/tracks
的 http 請求,打上 method=POST
的標簽,就會形成具體的 http 請求)。該查詢語言在這些指標和標簽列表的基礎上進行過濾和聚合。改變任何度量指標上的任何標簽值(包括添加或刪除指標),都會創建新的時間序列。
標簽的名稱只能由 ASCII 字符、數字以及下划線組成並滿足正則表達式 [a-zA-Z_][a-zA-Z0-9_]*
。其中以 __
作為前綴的標簽,是系統保留的關鍵字,只能在系統內部使用。標簽的值則可以包含任何 Unicode
編碼的字符。
3.2、樣本(sample)
在時間序列中的每一個點稱為一個樣本(sample),樣本由以下三部分組成:
- 指標(metric):指標名稱和描述當前樣本特征的 labelsets;
- 時間戳(timestamp):一個精確到毫秒的時間戳;
- 樣本值(value): 一個 folat64 的浮點型數據表示當前樣本的值。
3.3、表示方式
通過如下表達方式表示指定指標名稱和指定標簽集合的時間序列:
<metric name>{<label name>=<label value>, ...}
例如,指標名稱為 api_http_requests_total
,標簽為 method="POST"
和 handler="/messages"
的時間序列可以表示為:
api_http_requests_total{method="POST", handler="/messages"}
參考:
https://fuckcloudnative.io/prometheus/2-concepts/metric_types.html