天天看點

Prometheus之PromQL進階

一 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響應碼在該類請求中所占的比例;
  • 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所占比例;

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

七 PromQL查詢示例

繼續閱讀