Prometheus監控學習筆記之PromQL 內置函數


 

概述

Prometheus 提供了其它大量的內置函數,可以對時序數據進行豐富的處理。某些函數有默認的參數,例如:year(v=vector(time()) instant-vector)。其中參數 v 是一個瞬時向量,如果不提供該參數,將使用默認值 vector(time())。instant-vector 表示參數類型。

 

abs()

abs(v instant-vector) 返回輸入向量的所有樣本的絕對值。

 

absent()

absent(v instant-vector),如果傳遞給它的向量參數具有樣本數據,則返回空向量;如果傳遞的向量參數沒有樣本數據,則返回不帶度量指標名稱且帶有標簽的時間序列,且樣本值為1。

當監控度量指標時,如果獲取到的樣本數據是空的, 使用 absent 方法對告警是非常有用的。例如:

# 這里提供的向量有樣本數據
absent(http_requests_total{method="get"})  => no data
absent(sum(http_requests_total{method="get"}))  => no data

# 由於不存在度量指標 nonexistent,所以 返回不帶度量指標名稱且帶有標簽的時間序列,且樣本值為1
absent(nonexistent{job="myjob"})  => {job="myjob"}  1
# 正則匹配的 instance 不作為返回 labels 中的一部分
absent(nonexistent{job="myjob",instance=~".*"})  => {job="myjob"}  1

# sum 函數返回的時間序列不帶有標簽,且沒有樣本數據
absent(sum(nonexistent{job="myjob"}))  => {}  1

 

ceil()

ceil(v instant-vector) 將 v 中所有元素的樣本值向上四舍五入到最接近的整數。例如:

node_load5{instance="192.168.1.75:9100"} # 結果為 2.79
ceil(node_load5{instance="192.168.1.75:9100"}) # 結果為 3

 

changes()

changes(v range-vector) 輸入一個區間向量, 返回這個區間向量內每個樣本數據值變化的次數(瞬時向量)。例如

# 如果樣本數據值沒有發生變化,則返回結果為 1
changes(node_load5{instance="192.168.1.75:9100"}[1m]) # 結果為 1

 

clamp_max()

clamp_max(v instant-vector, max scalar) 函數,輸入一個瞬時向量和最大值,樣本數據值若大於 max,則改為 max,否則不變。例如:

node_load5{instance="192.168.1.75:9100"} # 結果為 2.79
clamp_max(node_load5{instance="192.168.1.75:9100"}, 2) # 結果為 2

 

clamp_min()

clamp_min(v instant-vector, min scalar) 函數,輸入一個瞬時向量和最小值,樣本數據值若小於 min,則改為 min,否則不變。例如:

node_load5{instance="192.168.1.75:9100"} # 結果為 2.79
clamp_min(node_load5{instance="192.168.1.75:9100"}, 3) # 結果為 3

 

day_of_month()

day_of_month(v=vector(time()) instant-vector) 函數,返回被給定 UTC 時間所在月的第幾天。返回值范圍:1~31。

 

day_of_week()

day_of_week(v=vector(time()) instant-vector) 函數,返回被給定 UTC 時間所在周的第幾天。返回值范圍:0~6,0 表示星期天。

 

days_in_month()

days_in_month(v=vector(time()) instant-vector) 函數,返回當月一共有多少天。返回值范圍:28~31。

 

 

delta()

delta(v range-vector) 的參數是一個區間向量,返回一個瞬時向量。它計算一個區間向量 v 的第一個元素和最后一個元素之間的差值。由於這個值被外推到指定的整個時間范圍,所以即使樣本值都是整數,你仍然可能會得到一個非整數值。

例如,下面的例子返回過去兩小時的 CPU 溫度差:

delta(cpu_temp_celsius{host="zeus"}[2h])

這個函數一般只用在 Gauge 類型的時間序列上。

 

deriv()

deriv(v range-vector) 的參數是一個區間向量,返回一個瞬時向量。它使用簡單的線性回歸計算區間向量 v 中各個時間序列的導數。

這個函數一般只用在 Gauge 類型的時間序列上。

 

exp()

exp(v instant-vector) 函數,輸入一個瞬時向量,返回各個樣本值的 e 的指數值,即 e 的 N 次方。當 N 的值足夠大時會返回 +Inf。特殊情況為:

  • Exp(+Inf) = +Inf

  • Exp(NaN) = NaN

 

floor()

floor(v instant-vector) 函數與 ceil() 函數相反,將 v 中所有元素的樣本值向下四舍五入到最接近的整數。

 

histogram_quantile()

histogram_quantile(φ float, b instant-vector) 從 bucket 類型的向量 b 中計算 φ (0 ≤ φ ≤ 1) 分位數(百分位數的一般形式)的樣本的最大值。(有關 φ 分位數的詳細說明以及直方圖指標類型的使用,請參閱直方圖和摘要)。向量 b 中的樣本是每個 bucket 的采樣點數量。每個樣本的 labels 中必須要有 le 這個 label 來表示每個 bucket 的上邊界,沒有 le 標簽的樣本會被忽略。直方圖指標類型自動提供帶有 _bucket 后綴和相應標簽的時間序列。

可以使用 rate() 函數來指定分位數計算的時間窗口。

例如,一個直方圖指標名稱為 employee_age_bucket_bucket,要計算過去 10 分鍾內 第 90 個百分位數,請使用以下表達式:

histogram_quantile(0.9, rate(employee_age_bucket_bucket[10m]))

返回:

{instance="10.0.86.71:8080",job="prometheus"} 35.714285714285715

這表示最近 10 分鍾之內 90% 的樣本的最大值為 35.714285714285715。

這個計算結果是每組標簽組合成一個時間序列。我們可能不會對所有這些維度(如 jobinstancemethod)感興趣,並希望將其中的一些維度進行聚合,則可以使用 sum() 函數。例如,以下表達式根據 job 標簽來對第 90 個百分位數進行聚合:

# histogram_quantile() 函數必須包含 le 標簽
histogram_quantile(0.9, sum(rate(employee_age_bucket_bucket[10m])) by (job, le))

如果要聚合所有的標簽,則使用如下表達式:

histogram_quantile(0.9,sum(rate(employee_age_bucket_bucket[10m])) by (le))

[info] 注意

histogram_quantile 這個函數是根據假定每個區間內的樣本分布是線性分布來計算結果值的(也就是說它的結果未必准確),最高的 bucket 必須是 le="+Inf" (否則就返回 NaN)。

如果分位數位於最高的 bucket(+Inf) 中,則返回第二個最高的 bucket 的上邊界。如果該 bucket 的上邊界大於 0,則假設最低的 bucket 的的下邊界為 0,這種情況下在該 bucket 內使用常規的線性插值。

如果分位數位於最低的 bucket 中,則返回最低 bucket 的上邊界。

如果 b 含有少於 2 個 buckets,那么會返回 NaN,如果 φ < 0 會返回 -Inf,如果 φ > 1 會返回 +Inf

 

holt_winters()

holt_winters(v range-vector, sf scalar, tf scalar) 函數基於區間向量 v,生成時間序列數據平滑值。平滑因子 sf 越低, 對舊數據的重視程度越高。趨勢因子 tf 越高,對數據的趨勢的考慮就越多。其中,0< sf, tf <=1

holt_winters 僅適用於 Gauge 類型的時間序列。

 

hour()

hour(v=vector(time()) instant-vector) 函數返回被給定 UTC 時間的當前第幾個小時,時間范圍:0~23。

 

idelta()

idelta(v range-vector) 的參數是一個區間向量, 返回一個瞬時向量。它計算最新的 2 個樣本值之間的差值。

這個函數一般只用在 Gauge 類型的時間序列上。

 

increase()

increase(v range-vector) 函數獲取區間向量中的第一個和最后一個樣本並返回其增長量, 它會在單調性發生變化時(如由於采樣目標重啟引起的計數器復位)自動中斷。由於這個值被外推到指定的整個時間范圍,所以即使樣本值都是整數,你仍然可能會得到一個非整數值。

例如,以下表達式返回區間向量中每個時間序列過去 5 分鍾內 HTTP 請求數的增長數:

increase(http_requests_total{job="apiserver"}[5m])

increase 的返回值類型只能是計數器類型,主要作用是增加圖表和數據的可讀性。使用 rate 函數記錄規則的使用率,以便持續跟蹤數據樣本值的變化。

 

irate()

irate(v range-vector) 函數用於計算區間向量的增長率,但是其反應出的是瞬時增長率。irate 函數是通過區間向量中最后兩個兩本數據來計算區間向量的增長速率,它會在單調性發生變化時(如由於采樣目標重啟引起的計數器復位)自動中斷。這種方式可以避免在時間窗口范圍內的“長尾問題”,並且體現出更好的靈敏度,通過irate函數繪制的圖標能夠更好的反應樣本數據的瞬時變化狀態。

例如,以下表達式返回區間向量中每個時間序列過去 5 分鍾內最后兩個樣本數據的 HTTP 請求數的增長率:

irate(http_requests_total{job="api-server"}[5m])

irate 只能用於繪制快速變化的計數器,在長期趨勢分析或者告警中更推薦使用 rate 函數。因為使用 irate 函數時,速率的簡短變化會重置 FOR 語句,形成的圖形有很多波峰,難以閱讀。

[info] 注意

當將 irate() 函數與聚合運算符(例如 sum())或隨時間聚合的函數(任何以 _over_time 結尾的函數)一起使用時,必須先執行 irate 函數,然后再進行聚合操作,否則當采樣目標重新啟動時 irate() 無法檢測到計數器是否被重置。

 

label_join()

label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)

函數可以將時間序列 v 中多個標簽 src_label 的值,通過 separator 作為連接符寫入到一個新的標簽 dst_label 中。可以有多個 src_label 標簽。

例如,以下表達式返回的時間序列多了一個 foo 標簽,標簽值為 etcd,etcd-k8s

up{endpoint="api",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"}
=> up{endpoint="api",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"} 1
 
label_join(up{endpoint="api",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"}, "foo", ",", "job", "service")
=> up{endpoint="api",foo="etcd,etcd-k8s",instance="192.168.123.248:2379",job="etcd",namespace="monitoring",service="etcd-k8s"} 1
label_replace()

為了能夠讓客戶端的圖標更具有可讀性,可以通過 label_replace 函數為時間序列添加額外的標簽。label_replace 的具體參數如下:

label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)

該函數會依次對 v 中的每一條時間序列進行處理,通過 regex 匹配 src_label 的值,並將匹配部分 relacement 寫入到 dst_label 標簽中。如下所示:

label_replace(up, "host", "$1", "instance", "(.*):.*")

函數處理后,時間序列將包含一個 host 標簽,host 標簽的值為 Exporter 實例的 IP 地址:

up{host="localhost",instance="localhost:8080",job="cadvisor"} 1
up{host="localhost",instance="localhost:9090",job="prometheus"} 1
up{host="localhost",instance="localhost:9100",job="node"} 1
ln()

ln(v instant-vector) 計算瞬時向量 v 中所有樣本數據的自然對數。特殊情況:

  • ln(+Inf) = +Inf

  • ln(0) = -Inf

  • ln(x < 0) = NaN

  • ln(NaN) = NaN

 

log2()

log2(v instant-vector) 函數計算瞬時向量 v 中所有樣本數據的二進制對數。特殊情況同上。

 

log10()

log10(v instant-vector) 計算瞬時向量 v 中所有樣本數據的十進制對數。特殊情況同上。

 

minute()

minute(v=vector(time()) instant-vector) 函數返回給定 UTC 時間當前小時的第多少分鍾。結果范圍:0~59。

 

month()

month(v=vector(time()) instant-vector) 函數返回給定 UTC 時間當前屬於第幾個月,結果范圍:0~12。

 

predict_linear()

predict_linear(v range-vector, t scalar) 函數可以預測時間序列 v 在 t 秒后的值。它基於簡單線性回歸的方式,對時間窗口內的樣本數據進行統計,從而可以對時間序列的變化趨勢做出預測。該函數的返回結果不帶有度量指標,只有標簽列表。

例如,基於 2 小時的樣本數據,來預測主機可用磁盤空間的是否在 4 個小時候被占滿,可以使用如下表達式:

predict_linear(node_filesystem_free{job="node"}[2h], 4 * 3600) < 0

通過下面的例子來觀察返回值:

predict_linear(http_requests_total{code="200",instance="120.77.65.193:9090",job="prometheus",method="get"}[5m], 5)
結果:
{code="200",handler="query_range",instance="120.77.65.193:9090",job="prometheus",method="get"} 1
{code="200",handler="prometheus",instance="120.77.65.193:9090",job="prometheus",method="get"} 4283.449995397104
{code="200",handler="static",instance="120.77.65.193:9090",job="prometheus",method="get"} 22.99999999999999
...

這個函數一般只用在 Gauge 類型的時間序列上。

 

rate()

rate(v range-vector) 函數可以直接計算區間向量 v 在時間窗口內平均增長速率,它會在單調性發生變化時(如由於采樣目標重啟引起的計數器復位)自動中斷。該函數的返回結果不帶有度量指標,只有標簽列表。

例如,以下表達式返回區間向量中每個時間序列過去 5 分鍾內 HTTP 請求數的每秒增長率:

rate(http_requests_total[5m])
結果:
{code="200",handler="label_values",instance="120.77.65.193:9090",job="prometheus",method="get"} 0
{code="200",handler="query_range",instance="120.77.65.193:9090",job="prometheus",method="get"} 0
{code="200",handler="prometheus",instance="120.77.65.193:9090",job="prometheus",method="get"} 0.2
...

rate() 函數返回值類型只能用計數器,在長期趨勢分析或者告警中推薦使用這個函數。

[info] 注意

當將 rate() 函數與聚合運算符(例如 sum())或隨時間聚合的函數(任何以 _over_time 結尾的函數)一起使用時,必須先執行 rate 函數,然后再進行聚合操作,否則當采樣目標重新啟動時 rate() 無法檢測到計數器是否被重置。

 

resets()

resets(v range-vector) 的參數是一個區間向量。對於每個時間序列,它都返回一個計數器重置的次數。兩個連續樣本之間的值的減少被認為是一次計數器重置。

這個函數一般只用在計數器類型的時間序列上。

 

round()

round(v instant-vector, to_nearest=1 scalar) 函數與 ceilfloor 函數類似,返回向量中所有樣本值的最接近的整數。to_nearest 參數是可選的,默認為 1,表示樣本返回的是最接近 1 的整數倍的值。你也可以將該參數指定為任意值(也可以是小數),表示樣本返回的是最接近它的整數倍的值。

 

scalar()

scalar(v instant-vector) 函數的參數是一個單元素的瞬時向量,它返回其唯一的時間序列的值作為一個標量。如果度量指標的樣本數量大於 1 或者等於 0, 則返回 NaN

 

sort()

sort(v instant-vector) 函數對向量按元素的值進行升序排序,返回結果:key: value = 度量指標:樣本值[升序排列]。

 

sort_desc()

sort(v instant-vector) 函數對向量按元素的值進行降序排序,返回結果:key: value = 度量指標:樣本值[降序排列]。

 

sqrt()

sqrt(v instant-vector) 函數計算向量 v 中所有元素的平方根。

 

time()

time() 函數返回從 1970-01-01 到現在的秒數。注意:它不是直接返回當前時間,而是時間戳

 

timestamp()

timestamp(v instant-vector) 函數返回向量 v 中的每個樣本的時間戳(從 1970-01-01 到現在的秒數)。

該函數從 Prometheus 2.0 版本開始引入。

 

vector()

vector(s scalar) 函數將標量 s 作為沒有標簽的向量返回,即返回結果為:key: value= {}, s。

 

year()

year(v=vector(time()) instant-vector) 函數返回被給定 UTC 時間的當前年份。

<aggregation>_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) : 區間向量內每個度量指標的總體標准方差。

[info] 注意

即使區間向量內的值分布不均勻,它們在聚合時的權重也是相同的。

 


免責聲明!

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



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