一 Prometheus的聚合函數
- 一般來說,單個指標的價值不大,監控場景中往往需要聯合並可視化一組指標,這種聯合機制即是指“聚合”操作,例如,將計算數、求和、平均值。分位數、標准差及方差等統計函數應用於時間序列的樣本之上生成具有統計學意義的結果等;
- 對查詢結果事前按照某種分類機制進行分組(groupby)並將查詢結果按組進行聚合計算也是較為常見的需求,例如分組統計、分組求平均值、分組求和等。
- 聚合操作由聚合函數針對一組值進行計算並返回單個值或少量幾值作為結果;
- Prometheus內置提供了11個聚合函數也成聚合運算符;
- 這些運算符僅支持應用於單個即時向量的元素,其返回值也是具有少量元素的新向量或標量;
- 這些聚合運算符即可以基於向量表達式返回結果中的時間序列的所有標簽維度進行分組聚合,也可以基於指定的標簽維度分組后在進行分組聚合;
二 聚合表達式
- PromQL中的聚合操作語法格式可采用如下兩種格式之一:
- <aggr-op>([parameter,]<vector exoression>) [without|by(<label list>)]
- <aggr-op>[without|by(<label list>)] ([parameter,]<vector exoression>)
- 分組聚合:先分組、后聚合
- without:從結果向量中刪除由without子句指定的標簽,未指定的那部分標簽則用作分組標准;
- by:功能與without剛好相反,它僅使用by字句中指定的標簽進行聚合,結果向量中出現但未被by子句指定的標簽則會被忽略;
- 為了保留上下文信息,使用by字句時需要顯示指定其結果中原本出現的job、instance等一類標簽;
- 事實上,各函數工作機制的不同之處也僅在於計算操作本身,PromQL對於它們的執行邏輯相似;
三 聚合函數
官方文檔:https://prometheus.io/docs/prometheus/latest/querying/operators/
- sum():對樣本值求和;
- avg():對樣本值求平均值這是進行指標數據分析的標准方法;
- count():對分組內的時間序列進行數量統計;
- stddev():對樣本值求標准差,以幫助用戶了解數據的波動大小(或稱之為波動程度)
- stdvar():對樣本值求方差,它是求取標准差過程的中間狀態;
- min():求取樣本值的最小值;
- max():求取樣本值的最大值;
- topk():逆序返回分組內的樣本值最大的前k個時間序列及其值;
- bottomk():順序返回分組內的樣本值最小的前k個時間序列及其值;
- quantile():分位數用於評估數據的分布狀態,該函數會返回分組內指定的分位數的值,即數值落在小於等於指定的分位區間的比例;
- count_values():對分組內的時間序列的樣本值進行數量統計;
四 二元運算符
- PromQL支持基本的算術運算和邏輯運算,這類運算支持使用操作符連接兩個操作數,以內也稱為二元運算符或二元操作符;
- 支持的運算
- 兩個標量間運算;
- 即時向量和標量間的運算:將運算符應用於向量上的每個樣本;
- 兩個即時向量間的運算:遵循向量匹配機制;
- 將運算符用於兩個即時向量間的運算時,可基於向量匹配模式(Vector Matching)定義其運算機制;
- 支持的運算
- 算術運算
- 支持的運算符:+(加)、-(減)、*(乘)、/(除)、%(取模)和^(冪運算);
- 比較運算
- 支持的運算符:==(等值比較)、!=(不等)、>、<、>=、<=(小於等於);
- 邏輯/集合運算
- 支持的運算符:and(並且)、or(或者)和unless(除了);
- 目前,該運算僅允許在兩個即時向量間進行,尚不支持標量參與運算;
五 二元運算符優先級
- Prometheus的復雜運算中,二元運算符存在如下給定次序中所示的由高到低的優先級;
- ^
- *,/,%
- +,-
- ==,!=,<=,<,>=,>
- and,unless
- or
- 具有相同優先級的運算符滿足結合律(左結合),但冪運算除外,因為它是右結合機制,例如:
2 * 3 % 2
相當於(2 * 3) % 2
2 ^ 3 ^ 2
等價於2 ^ (3 ^ 2)
- 可以使用括號()改變運算次序;
六 向量匹配
官方文檔:https://prometheus.io/docs/prometheus/latest/querying/operators/
- 即時向量間的運算時PromQL的特色之一;運算時,PromQL為會左側向量中的每個元素找到匹配的元素,其匹配行為有兩種基本類型;
- 一對一
- 一對多或多對一
6.1 即時向量一對一匹配
- 從運算符的兩邊表達式所獲取的即時向量間一次比較,並找到唯一匹配(標簽完全一致)的樣本值;
- 找不到匹配項的值則不會出現在結果中;
- 匹配表達式語法
- <vector expr> <bin-op>ignoring(<label list>) <vector expr>
- <vector expr> <bin-op>on(<label list>)<vector expr>
- ignore:定義匹配檢測時要忽略的標簽;
- on:定義匹配檢測是只使用的標簽;
- 例如,rate(http_requests_total{status_code=~"5.*"}[5m]) > rate(http_requests_total[5m]) * 0.1
- 左側會生成一個即時向量,它計算出5xx響應碼的各類請求的增長速率;
- 除了status_code標簽外,改指標通常還有其它標簽:於是,status_code的值為500的標簽同其它標簽的每個組合將代表一個時間序列,其相應的即時樣本即為結果向量的一個元素;
- 右側會生成一個即時向量,它計算出所有標簽組合所代表的各類請求的增長速率;
- 計算時,PromQL會在操作符左右兩側的結果元素中找到標簽完全一致的元素進行比較;
- 其意義為,計算出每類請求中的500響應碼在該類請求中所占的比例;
- 左側會生成一個即時向量,它計算出5xx響應碼的各類請求的增長速率;
- Example input
- method_code:http_errors:rate5m{method="get", code="500"} 24 #響應碼為500,請求方法為get方法的時間序列個數為24個
- method_code:http_errors:rate5m{method="put", code="501"} 3 #響應碼為501,請求方法為put方法的時間序列個數為3個
- method_code:http_errors:rate5m{method="post", code="500"} 6 # 響應碼為500,請求方法為post方法的時間序列個數為21個
- method_code:http_errors:rate5m{method="post", code="404"} 21 #響應碼為404,請求方法為post方法的時間序列個數為21個
- method:http_requests:rate5m{method="get"} 600
- method:http_requests:rate5m{method="del"} 34
- method:http_requests:rate5m{method="post"} 120
- Example query
- method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
- method_code:http_errors:rate5m{code="500"} #獲取的及時向量為: method_code:http_errors:rate5m{method="get", code="500"} 24,method_code:http_errors:rate5m{method="post", code="500"} 6;
- method:http_requests:rate5m #獲取的即時向量: method:http_requests:rate5m{method="get"} 600,method:http_requests:rate5m{method="del"} 34 #由於左測沒有del方法,忽略該值,method:http_requests:rate5m{method="post"} 120;
- / #做除法運算
- ignoring(code) #忽略code,找到左側標簽與右側標簽相同的做除法運算, method="get":24/600=0.04 在所有get請求中響應碼為500所占的比例, method="post":6/120=0.05 在所有post請求中,響應碼為500所占比例;
- method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
6.2 一對多/多對一匹配
- “一”側的每個元素,可與“多”側的多個元素進行匹配;
- 必須使用group_left或group_right明確指定哪側為“多”側;
- 匹配表達式語法;
- <vector expr> <bin-op>ignoring(<label list>) group_left (<label list>) <vector expr> #group_left 左側為多側 忽略指定的標簽作比較
- <vector expr> <bin-op>ignoring(<label list>) group_right (<label list>) <vector expr> #group_right 右側為多側 忽略指定的標簽作比較
- <vector expr> <bin-op>on(<label list>) group_left (<label list>) <vector expr> # 只根據指定標簽做比較
- <vector expr> <bin-op>on(<label list>) group_right (<label list>) <vector expr> #
- Example input
- method_code:http_errors:rate5m{method="get", code="500"} 24 #響應碼為500,請求方法為get方法的時間序列個數為24個
- method_code:http_errors:rate5m{method="put", code="501"} 3 #響應碼為501,請求方法為put方法的時間序列個數為3個
- method_code:http_errors:rate5m{method="post", code="500"} 6 # 響應碼為500,請求方法為post方法的時間序列個數為21個
- method_code:http_errors:rate5m{method="post", code="404"} 21 #響應碼為404,請求方法為post方法的時間序列個數為21個
- method:http_requests:rate5m{method="get"} 600
- method:http_requests:rate5m{method="del"} 34
- method:http_requests:rate5m{method="post"} 120
- Example query:
- method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
- method_code:http_errors:rate5m #獲取所有的查詢結果 24、3、6、21
- 左側為多側 ,左側多個值對用右側一個值
- 忽略code
- {method="get", code="500"} 所占比例為:24 / 600=0.04
- {method="post", code="500"} 所占比例為: 6 / 120=0.05
- {method="post", code="404"} 所占比例為:21 / 120=0.175
- method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
七 常用函數
https://prometheus.io/docs/prometheus/latest/querying/functions/
abs()
absent()
absent_over_time()
ceil()
changes()
clamp()
clamp_max()
clamp_min()
day_of_month()
day_of_week()
day_of_year()
days_in_month()
delta()
deriv()
exp()
floor()
histogram_count() and histogram_sum()
histogram_fraction()
histogram_quantile()
holt_winters()
hour()
idelta()
increase()
irate()
label_join()
label_replace()
ln()
log2()
log10()
minute()
month()
predict_linear()
rate()
resets()
round()
scalar()
sgn()
sort()
sort_desc()
sqrt()
time()
timestamp()
vector()
year()
八 PromQL查詢示例
參考官方文檔:https://prometheus.io/docs/prometheus/latest/querying/examples/