PromQL全解析


PromQL(Prometheus Query Language)為Prometheus tsdb的查詢語言。是結合grafana進行數據展示和告警規則的配置的關鍵部分。

本文默認您已了解Prometheus的四種指標類型:

  • counter(計數器)
  • gauge (儀表類型)
  • histogram(直方圖類型)
  • summary (摘要類型)

便於讀者實踐,本文大部分樣本數據target:

  • Prometheus
  • node_exporter

表達式數據類型


PromQL查詢語句即表達式,實現的四種數據類型:

Instant vector

Instance vector(瞬時向量)表示一個時間序列的集合,但是每個時序只有最近的一個點,而不是線。

image-20220306234734684

Range vector

Range vector(范圍向量)表示一段時間范圍里的時序,每個時序可包含多個點

image-20220306234624646

sources:Understanding Prometheus Range Vectors

Scalar

Scalar(標量)通常為數值,可以將只有一個時序的Instance vector轉換成Scalar。

String

簡單字符串值,目前未被使用。

選擇器


標簽選擇器

查詢Prometheus http狀態碼為400的請求數量。

prometheus_http_requests_total{code="400"}

image-20220304143538179

標簽匹配運算符:

  • =:與字符串匹配
  • !=:與字符串不匹配
  • =~:與正則匹配
  • !~:與正則不匹配

查詢Prometheus http狀態碼為4xx或5xx並且handler為/api/v1/query的請求數量

prometheus_http_requests_total{code=~"4.*|5.*",handler="/api/v1/query"}

內部標簽__name__用來匹配指標名稱,下面的表達式與上一條等價

{code=~"4.*|5.*",handler="/api/v1/query",__name__="prometheus_http_requests_total"}
范圍選擇器

查詢過去5分鍾Prometheus健康檢查的采樣記錄。

prometheus_http_requests_total{code="200",handler="/-/healthy"}[5m]

image-20220304164256208

單位:mssmhdwy

時間串聯:[1h5m]一小時5分鍾

時間偏移


通過offset

通過offset將時間倒退5分鍾,即查詢5分鍾之前的數據。

prometheus_http_requests_total{code="200"} offset 5m

image-20220304212139634

同樣支持查詢range vector

prometheus_http_requests_total{code="200"}[3m] offset 5m
@修飾符

還可以通過@ 直接跳轉到某個uinx時間戳,需開啟啟動參數--enable-feature=promql-at-modifier

prometheus_http_requests_total{code="200"} @ 1646089826

運算符


Prometheus中的運算符與各類編程語言中的基本一致。

數學運算符

Prometheus 中存在以下數學運算符:

  • +(加法)
  • -(減法)
  • *(乘法)
  • /(除法)
  • %(取模)
  • ^(冪)

兩個標量之間的計算

10/3

image-20220305003059797

瞬時向量與標量計算,由於計算后值意義與原指標名有差異,Prometheus很貼心的幫我們移除了指標名稱。

prometheus_http_response_size_bytes_sum / 1024

image-20220305005645428

兩個瞬時向量間的計算,如下計算node的內存使用率

(
1 -
node_memory_MemAvailable_bytes{job="node",instance="localhost:9100"} 
/ node_memory_MemTotal_bytes{job="node",instance="localhost:9100"}
)
* 100

image-20220305135606398

如果兩個瞬時向量標簽不一致可通過ignoring忽略多余標簽

輸入示例:

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="get"}  600
method:http_requests:rate5m{method="post"} 120

查詢示例:

method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m

結果示例:

{method="get"}  0.04            //  24 / 600
{method="post"} 0.05            //   6 / 120

如果兩個瞬時向量數量不一致時可通過group_leftgroup_right指定以那一側為准

輸入示例:

method_code:http_errors:rate5m{method="get", code="500"}  24
method_code:http_errors:rate5m{method="get", code="404"}  30
method_code:http_errors:rate5m{method="put", code="501"}  3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120

查詢示例:

group_left以左側為准

method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m

結果示例:

{method="get", code="500"}  0.04            //  24 / 600
{method="get", code="404"}  0.05            //  30 / 600
{method="post", code="500"} 0.05            //   6 / 120
{method="post", code="404"} 0.175           //  21 / 120
比較運算符

Prometheus 中存在以下比較運算符:

  • ==(相等)
  • !=(不相等)
  • >(大於)
  • <(小於)
  • >=(大於或等於)
  • <=(小於或等於)

兩個標量之間比較,在運算符后跟bool修飾,結果0( false) 或1 ( true)

10 < bool 5

image-20220305140444783

瞬時向量與標量比較,查詢node狀態

up{job="node"} ==  bool 1

image-20220305144157027

兩個瞬時向量比較,查看消息隊列容量狀態

prometheus_notifications_queue_length < bool prometheus_notifications_queue_capacity

image-20220305143955740

邏輯運算符

Prometheus 中存在以下邏輯運算符:

  • and(與)
  • or(或)
  • unless(非)

邏輯運算僅適用於向量

如下我們有4個target,進行相應的邏輯運算,實現和標簽選擇相似效果。

image-20220305183445996

up{instance!="192.168.1.123:9091"} and up{job!="alertmanager"}  

image-20220305183944382

up{instance="192.168.1.123:9091"} or up{job="alertmanager"}  

image-20220305183849660

up unless up{job="alertmanager"}  

image-20220305184304201

Prometheus 中二元運算符的優先級,從高到低。

  1. ^
  2. *, /, %,atan2
  3. +,-
  4. ==, !=, <=, <, >=,>
  5. and,unless
  6. or

相同優先級的運算符是左結合的

聚合運算符

Prometheus 支持以下內置聚合運算符,可用於聚合單個瞬時向量,生成新的向量:

  • sum(總和)

  • min(最小)

  • max(最大)

  • avg(平均值)

  • group(分組)

  • stddev(標准偏差)

  • stdvar(標准方差)

  • count(計算向量中的元素個數)

  • count_values(計算具有相同值的元素個數)

  • bottomk(樣本值的最小 k 個元素)

  • topk(按樣本值計算的最大 k 個元素)

  • quantile(分位數計算 φ-quantile (0 ≤ φ ≤ 1)

聚合運算符可通過 without、by 根據標簽擴展

summinmaxavg

計算http請求的總和,最大、最小請求的url的數量,平均數量

sum(prometheus_http_requests_total)

image-20220305230959842

通過狀態碼分別統計

image-20220305231557223

group:

類uniq的用法

image-20220305231747791

stddevstdvar

反映一組數據離散程度,用以衡量數據值偏離算術平均值的程度。標准偏差為方差的開平方,標准偏差越小,這些值偏離平均值就越少,反之亦然。

通過標准差來反映網絡波動

stddev(rate(node_network_transmit_bytes_total[5m]))

rate計算某段時間的速率

image-20220306005605026

countcount_values:

統計總共有幾個時序

count(prometheus_http_requests_total)

image-20220305233618880

計算每個value的數量

count_values("value",prometheus_http_requests_total)

image-20220305233949668

bottomktopk

計算value中最小的5個時序

bottomk(5,prometheus_http_requests_total)

image-20220305234204310

quantile:求數據的分位數

我們現在要找出K8s集群中所有node節點的內存使用率的分布情況

quantile
(0.8,
(
1 -
node_memory_MemAvailable_bytes{job="kubernetes-service-endpoints"} 
/ node_memory_MemTotal_bytes{job="kubernetes-service-endpoints"}
)
* 100
)

image-20220306192818545

直接可以看出80%的節點內存使用率在68%以下

函數


值取整

ceil()

ceil(v instant-vector)樣本數據向上取整。

ceil(node_load1)  #1.2-->2

floor()

floor(v instant-vector)與ceil()相反,floor()樣本值向下取整。

round()

round(v instant-vector, to_nearest=1 scalar) 對樣本值四舍五入取整。to_nearest 參數是可選的,默認為 1,表示樣本返回的是最接近 1 的整數倍的值,參數可以為分數。

取整

round(prometheus_engine_query_duration_seconds_sum)

取整到最近的5的倍數

round(prometheus_engine_query_duration_seconds_sum,5)
值截取

clamp()

clamp(v instant-vector, min scalar, max scalar) 截取所有元素的樣本值在 [min,max]集合內的樣本,如果min>max返回NaN

放回樣本值在10到20的樣本

clamp(prometheus_http_requests_total,10,20)

clamp_max()

clamp_max(v instant-vector, max scalar) 同clamp(),不過只限定樣本最大值

clamp_min()

clamp_min(v instant-vector, min scalar) 同clamp(),不過只限定樣本最小值

值變化統計

changes()

changes(v range-vector)返回某段時間內樣本值改變的次數

changes(node_load1[1m])  
復位統計

resets()

resets(v range-vector) 返回樣本范圍時間內的復位次數。與counter使用,兩個連續樣本之間值如有減少則被視為計數器復位。

查看上下文交換次數計數器在5分鍾內復位次數

resets(node_context_switches_total[5m])
日期與時間管理

day_of_month()

day_of_month(v=vector(time()) instant-vector)如果樣本值是utc時間,則返回這個時間所屬月份中的日期(1-31)

v=vector(time()) 為默認參數

day_of_month(node_boot_time_seconds)

day_of_week()

day_of_week(v=vector(time()) instant-vector) 同上,如果樣本值是utc時間,則返回這個時間所屬星期幾(0-6)

days_in_month()

days_in_month(v=vector(time()) instant-vector) 如果樣本值是utc時間,則返回這個時間所屬月份的天數(28-31)

hour()

hour(v=vector(time()) instant-vector)如果樣本值是utc時間,則返回這個時間所屬一天中的第幾個小時(1-13)

minute()

minute(v=vector(time()) instant-vector) 如果樣本值是utc時間,則返回這個時間所屬小時中的第幾分鍾(1-59)

month()

month(v=vector(time()) instant-vector)如果樣本值是utc時間,則返回這個時間所屬的月份(1-12)

year()

year(v=vector(time()) instant-vector)如果樣本值是utc時間,則返回這個時間所屬的年份

time()

返回自1970 年 1 月 1 日 UTC 以來的秒數,不是系統時間,而是表達式計算時那一刻的時間。

timestamp()

timestamp(v instant-vector)返回每個樣本值的時間戳,自 1970 年 1 月 1 日 UTC 以來的秒數。

直方圖分位數

histogram_quantile()

histogram_quantile(φ float, b instant-vector) 從 bucket 類型的向量 b 中計算 φ (0 ≤ φ ≤ 1) 分位數的樣本的最大值,與聚合運算符quantile相似。

計算80%請求的持續時間最大值。

histogram_quantile(0.8,rate(prometheus_http_request_duration_seconds_bucket[1d]))
差異與增長率

delta()

delta(v range-vector)計算范圍向量中每個時間序列元素的第一個值和最后一個值之間的差。與指標類型gauge一起使用

計算一天內內存可用量的變化

delta(node_memory_MemAvailable_bytes[1d])

idelta()

idelta(v range-vector)計算范圍向量中最后兩個樣本之間的差異。與指標類型gauge一起使用

idelta(node_memory_MemAvailable_bytes[1m])

increase()

increase(v range-vector) 計算時間范圍內的增量,與counter一起使用。它是速率rate(v)乘以時間范圍內秒數的語法糖,主要用於人類可讀性。

計算10分鍾內請求增長量

increase(prometheus_http_requests_total[10m])

rate()

rate(v range-vector)計算范圍向量中時間序列的平均每秒增長率。

過去10分鍾請求平均每秒增長率,與counter一起使用。

rate(prometheus_http_requests_total[10m])

irate()

irate(v range-vector) 通過時間范圍的最后兩個點來計算每秒瞬時增長率。

irate(prometheus_http_requests_total[10m])
label管理

label_join()

label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)為每個時間序列添加一個label,值為指定舊label的value連接

label_join(up{instance="localhost:9100", job="node"},"new_label","-","instance","job")

結果:

up{instance="localhost:9100", job="node", new_label="localhost:9100-node"}   1

label_replace()

label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)從源label中獲取value元素用於添加新的label

$1 獲取正則匹配,匹配值添加到hello標簽中

label_replace(up{instance="localhost:9100", job="node"},"hello","$1","job","(.*)")

結果:

up{hello="node", instance="localhost:9100", job="node"}       1
預測

predict_linear()

predict_linear(v range-vector, t scalar) 通過簡單線性回歸預測t秒后的樣本值,與gauge一起使用。

根據過去1小時的文件系統剩余空間量,預測1小時之后的剩余空間

predict_linear(node_filesystem_free_bytes[1h],3600)
轉換

absent()

absent(v instant-vector)如果向量有元素,則返回一個空向量;如果向量沒有元素,則返回值為 1。

設置如下告警表達式:

absent(up{job="node"} == 1)

由於up{job="node"} 不存在或值不為1則告警表達式的值為1 產生告警

absent_over_time()

absent_over_time(v range-vector)如果范圍向量有元素,則返回一個空向量;如果范圍向量沒有元素,則返回值為 1。

如果up{job="node1"}在某段時間不存在則返回1

absent_over_time(up{job="node1"}[1h])

scalar()

scalar(v instant-vector)以標量形式返回該單元素的樣本值,如果輸入向量不是正好一個元素,scalar將返回NaN.

vector()

vector(s scalar)將標量作為沒有標簽的向量返回。

sgn()

sgn(v instant-vector)返回一個向量,其中所有樣本值都轉換為1或-1或0

定義如下:

如果 v 為正,則為 1

如果 v 為負,則為 -1

如果 v 等於 0,則為 0。

排序

sort()

sort(v instant-vector)返回按樣本值升序排序的向量元素。

sort_desc()

與sort()相反,按降序排序。

_over_time()

下面的函數列表允許傳入一個范圍向量,返回一個帶有聚合的瞬時向量:

  • avg_over_time(range-vector): 區間向量內每個度量指標的平均值。
  • min_over_time(range-vector): 區間向量內每個度量指標的最小值。
  • max_over_time(range-vector): 區間向量內每個度量指標的最大值。
  • sum_over_time(range-vector): 區間向量內每個度量指標的求和值。
  • count_over_time(range-vector): 區間向量內每個度量指標的樣本數據個數。
  • quantile_over_time(scalar, range-vector): 區間向量內每個度量指標的樣本數據值分位數,φ-quantile (0 ≤ φ ≤ 1)
  • stddev_over_time(range-vector): 區間向量內每個度量指標的總體標准偏差。
  • stdvar_over_time(range-vector): 區間向量內每個度量指標的總體標准方差
數學函數

abs()

abs(v instant-vector) 返回樣本的絕對值。

sqrt()

sqrt(v instant-vector)計算樣本值的平方根。

deriv()

deriv(v range-vector) 使用簡單線性回歸計算時間序列在范圍向量中的每秒導數。與指標類型gauge一起使用

exp()

exp(v instant-vector)計算樣本值的指數函數。

特殊情況:

  • Exp(+Inf) = +Inf
  • Exp(NaN) = NaN

ln()、log2()、log10()

ln/log2/log10(v instant-vector) 計算樣本值對數

特殊情況(同適用於log2/log10):

  • ln(+Inf) = +Inf
  • ln(0) = -Inf
  • ln(x < 0) = NaN
  • ln(NaN) = NaN

holt_winters()

holt_winters(v range-vector, sf scalar, tf scalar)基於訪問向量v,生成時間序列數據平滑數據值。平滑因子sf越低, 對舊數據越重要。趨勢因子tf越高,更關心趨勢數據。0<sf,tf<=1。 與gauge一起使用

三角函數、弧度

  • acos(v instant-vector)
  • acosh(v instant-vector)
  • asin(v instant-vector)
  • asinh(v instant-vector)
  • atan(v instant-vector)
  • atanh(v instant-vector)
  • cos(v instant-vector)
  • cosh(v instant-vector)
  • sin(v instant-vector)
  • sinh(v instant-vector)
  • tan(v instant-vector)
  • tanh(v instant-vector)

角度、弧度轉化

  • deg(v instant-vector)
  • pi()
  • rad(v instant-vector)

如果內容有誤請指正。通過博客閱讀:iqsing.github.io

參考

[1] Understanding Prometheus Range Vectors: https://satyanash.net/software/2021/01/04/understanding-prometheus-range-vectors.html

[2] promethues: https://prometheus.io/docs/prometheus/latest/querying/basics/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM