查詢基礎
Prometheus 提供了一種功能性的查詢語言,稱為 PromQL (Prometheus Query Language),允許使用者即時選擇和聚合時間序列資料。
當您向 Prometheus 傳送查詢請求時,它可以是在單個時間點求值的瞬時查詢 (instant query),也可以是在開始時間和結束時間之間以等間隔步長求值的範圍查詢 (range query)。在兩種情況下,PromQL 的工作原理完全相同;範圍查詢就像是在不同時間戳上多次執行的瞬時查詢。
在 Prometheus UI 中,“Table” 標籤頁用於瞬時查詢,“Graph” 標籤頁用於範圍查詢。
其他程式可以透過 HTTP API 獲取 PromQL 表示式的結果。
示例
本文件是 Prometheus 基礎語言參考。在學習時,從幾個 示例 開始可能會更容易。
樣本
PromQL 返回的給定時間戳下的樣本值可能是一個浮點數(float)或一個原生直方圖 (native histogram)。浮點數樣本是一個簡單的浮點數值,而原生直方圖樣本則包含完整的直方圖,包括計數 (count)、總和 (sum) 和桶 (bucket)。
請注意,PromQL 文件中的“直方圖樣本 (histogram sample)”一詞始終指代原生直方圖。“經典直方圖 (classic histogram)”一詞是指一組包含帶有 _bucket、_count 和 _sum 字尾的浮點數樣本的時間序列,它們共同描述了一個直方圖。從 PromQL 的角度來看,這些只包含浮點數樣本,不存在“經典直方圖樣本”。
浮點數樣本和直方圖樣本都可以具有計數器 (counter) 或儀表盤 (gauge) 的“特性(flavor)”。具有計數器或儀表盤特性的浮點數樣本通常分別簡稱為“計數器”或“儀表盤”,而它們對應的直方圖則稱為“計數器直方圖”或“儀表盤直方圖”。浮點數樣本本身不儲存其特性,需要使用者在編寫 PromQL 查詢時自行考慮其特性。(按照慣例,包含浮點數計數器的時間序列名稱以 _total 結尾,以幫助區分。)
由於直方圖樣本“知道”它們是計數器特性還是儀表盤特性,因此可以針對不匹配的操作提供可靠的警告。例如,對儀表盤浮點數應用 rate 函式極有可能產生無意義的結果,但查詢仍會在沒有任何抱怨的情況下被處理。然而,如果將其應用於儀表盤直方圖,查詢結果中將會標註一條警告。
表示式語言資料型別
在 Prometheus 的表示式語言中,一個表示式或子表示式可以計算為以下四種類型之一:
- 瞬時向量 (Instant vector) - 一組時間序列,每個時間序列包含單個樣本,它們共享相同的時間戳
- 範圍向量 (Range vector) - 一組時間序列,包含每個時間序列隨時間變化的一系列資料點
- 標量 (Scalar) - 一個簡單的數字浮點值
- 字串 (String) - 一個簡單的字串值;目前未使用
根據使用場景(例如:繪製圖表對比顯示錶達式輸出),只有其中某些型別可以作為使用者指定表示式的合法結果。對於 瞬時查詢,允許使用上述任何資料型別作為表示式的根。而 範圍查詢 僅支援標量型別和瞬時向量型別的表示式。
向量和時間序列都可能包含浮點數樣本和直方圖樣本的混合。
直方圖桶佈局的協調一致
原生直方圖可以具有不同的桶佈局,但它們通常可以轉換為相容的版本,以便對其應用二元和聚合操作。作用於範圍向量且適用於原生直方圖的函式也會執行此類協調。在二元操作中,這種協調是成對執行的;在聚合操作和函式中,所有直方圖樣本都會協調為一個相容的桶佈局。
並不是所有的桶佈局都可以協調,如果在操作中遇到不相容的直方圖,相應的輸出向量元素將從結果中移除,並標記為警告級別的註釋。更多詳細資訊可以在 原生直方圖規範 中找到。
字面量
以下部分描述了各種型別的字面量值。請注意,不存在“直方圖字面量”。
字串字面量
字串字面量可以使用單引號、雙引號或反引號來指定。
PromQL 遵循與 Go 相同的轉義規則 。對於單引號或雙引號中的字串字面量,反斜槓表示轉義序列的開始,其後可以跟 a、b、f、n、r、t、v 或 \。可以使用八進位制 (\nnn) 或十六進位制 (\xnn、\unnnn 和 \Unnnnnnnn) 表示法來提供特定字元。
相反,在反引號指定的字串字面量中,跳脫字元不會被解析。需要特別注意的是,與 Go 不同,Prometheus 不會丟棄反引號內的換行符。
示例
"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t`
浮點數字面量和時間持續時間
標量浮點值可以寫為字面量整數或浮點數,格式如下(空格僅為了提高可讀性):
[-+]?(
[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?
| 0[xX][0-9a-fA-F]+
| [nN][aA][nN]
| [iI][nN][fF]
)
示例
23
-2.43
3.4e-9
0x8f
-Inf
NaN
此外,可以在十進位制或十六進位制數字之間使用下劃線 (_) 以提高可讀性。
示例
1_000_000
.123_456_789
0x_53_AB_F3_82
浮點數字面量也用於指定以秒為單位的時間持續時間。為了方便,十進位制整數可以與以下時間單位結合使用:
ms– 毫秒s– 秒 – 1s 等於 1000msm– 分鐘 – 1m 等於 60s(忽略閏秒)h– 小時 – 1h 等於 60md– 天 – 1d 等於 24h(忽略所謂的夏令時)w– 周 – 1w 等於 7dy– 年 – 1y 等於 365d(忽略閏年)
在十進位制整數後加上上述單位之一,是與普通浮點數字面量等效秒數的不同表示形式。
示例
1s # Equivalent to 1.
2m # Equivalent to 120.
1ms # Equivalent to 0.001.
-2h # Equivalent to -7200.
以下示例不適用:
0xABm # No suffixing of hexadecimal numbers.
1.5h # Time units cannot be combined with a floating point.
+Infd # No suffixing of ±Inf or NaN.
多個單位可以透過拼接帶有後綴的整數來組合。單位必須按從長到短的順序排列。在單個浮點數字字面量中,給定的單位只能出現一次。
示例
1h30m # Equivalent to 5400s and thus 5400.
12h34m56s # Equivalent to 45296s and thus 45296.
54s321ms # Equivalent to 54.321.
時間序列選擇器
這些是指導 PromQL 抓取什麼資料的基本構建塊。
瞬時向量選擇器
瞬時向量選擇器允許在給定的時間戳(時間點)選擇一組時間序列併為每個時間序列獲取單個樣本值。在最簡單的形式中,僅指定指標名稱,這將返回一個包含具有該指標名稱的所有時間序列元素的瞬時向量。
返回的值將是在查詢評估時間戳當天或之前最新的樣本值(如果是 瞬時查詢),或者是查詢中的當前步長值(如果是 範圍查詢)。@ 修飾符 允許覆蓋進行選擇的時間戳。僅當時間序列的最新樣本在不超過 回溯期 之前時,才會返回該時間序列。
此示例選擇具有 http_requests_total 指標名稱的所有時間序列,並返回每個序列的最新樣本:
http_requests_total
可以透過在花括號 ({}) 中附加逗號分隔的標籤匹配器列表來進一步過濾這些時間序列。
此示例僅選擇指標名稱為 http_requests_total 且 job 標籤設定為 prometheus、group 標籤設定為 canary 的時間序列:
http_requests_total{job="prometheus",group="canary"}
還可以對標籤值進行否定匹配,或者利用正則表示式匹配標籤值。存在以下標籤匹配運算子:
=:選擇與提供的字串完全相等的標籤。!=:選擇與提供的字串不相等的標籤。=~:選擇與提供的字串進行正則匹配的標籤。!~:選擇與提供的字串不進行正則匹配的標籤。
正則表示式 匹配是完全錨定的。env=~"foo" 的匹配將被視為 env=~"^foo$"。
例如,這將選擇適用於 staging、testing 和 development 環境且 HTTP 方法不為 GET 的所有 http_requests_total 時間序列。
http_requests_total{environment=~"staging|testing|development",method!="GET"}
匹配空標籤值的標籤匹配器也會選擇根本沒有設定該特定標籤的所有時間序列。同一個標籤名稱可以有多個匹配器。
例如,給定資料集:
http_requests_total
http_requests_total{replica="rep-a"}
http_requests_total{replica="rep-b"}
http_requests_total{environment="development"}
查詢 http_requests_total{environment=""} 將匹配並返回:
http_requests_total
http_requests_total{replica="rep-a"}
http_requests_total{replica="rep-b"}
並且會排除:
http_requests_total{environment="development"}
同一標籤名稱可以使用多個匹配器;它們必須全部透過才能返回結果。
查詢
http_requests_total{replica!="rep-a",replica=~"rep.*"}
然後會匹配
http_requests_total{replica="rep-b"}
向量選擇器必須指定一個名稱,或者至少指定一個不匹配空字串的標籤匹配器。以下表達式是非法的:
{job=~".*"} # Bad!
相反,這些表示式是有效的,因為它們都具有一個不匹配空標籤值的選擇器。
{job=~".+"} # Good!
{job=~".*",method="get"} # Good!
標籤匹配器還可以透過匹配內部的 __name__ 標籤來應用於指標名稱。例如,表示式 http_requests_total 等同於 {__name__="http_requests_total"}。也可以使用 = 以外的匹配器 (!=, =~, !~)。以下表達式選擇名稱以 job: 開頭的所有指標:
{__name__=~"job:.*"}
指標名稱不能是以下關鍵字之一:bool、on、ignoring、group_left 和 group_right。以下表達式是非法的:
on{} # Bad!
針對此限制的一種解決方法是使用 __name__ 標籤:
{__name__="on"} # Good!
範圍向量選擇器
範圍向量字面量的工作原理類似於瞬時向量字面量,不同之處在於它們選擇的是從當前瞬間回溯的一定範圍內的樣本。在語法上,在向量選擇器的末尾新增一箇中括號 ([]) 圍起來的 浮點數字面量,以指定應為每個生成的範圍向量元素獲取多少秒前的時間值。通常,浮點數字面量使用包含一個或多個時間單位的語法,例如 [5m]。該範圍是一個左開右閉的區間,即時間戳與範圍左邊界重合的樣本將被排除在選擇之外,而與範圍右邊界重合的樣本將被包含在選擇之內。
在這個示例中,我們為所有指標名稱為 http_requests_total 且 job 標籤設定為 prometheus 的時間序列,選擇在過去 5 分鐘內記錄的所有值:
http_requests_total{job="prometheus"}[5m]
Offset 修飾符
offset 修飾符允許更改查詢中單個瞬時和範圍向量的時間偏移量。
例如,以下表達式返回相對於當前查詢評估時間 5 分鐘前的 http_requests_total 的值:
http_requests_total offset 5m
請注意,offset 修飾符始終需要緊跟在選擇器後面,即以下寫法是正確的:
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
而以下寫法是不正確的:
sum(http_requests_total{method="GET"}) offset 5m // INVALID.
範圍向量同樣適用。這將返回一週前 http_requests_total 的 5 分鐘 速率 (rate):
rate(http_requests_total[5m] offset 1w)
在查詢過去的樣本時,負偏移量將允許在時間上進行向前的時間對比:
rate(http_requests_total[5m] offset -1w)
請注意,這允許查詢提前檢視其評估時間之後的資料。
@ 修飾符
@ 修飾符允許更改查詢中單個瞬時和範圍向量的評估時間。提供給 @ 修飾符的時間是一個 Unix 時間戳,並用浮點數字面量描述。
例如,以下表達式返回在 2021-01-04T07:40:00+00:00 時的 http_requests_total 的值:
http_requests_total @ 1609746000
請注意,@ 修飾符始終需要緊跟在選擇器後面,即以下寫法是正確的:
sum(http_requests_total{method="GET"} @ 1609746000) // GOOD.
而以下寫法是不正確的:
sum(http_requests_total{method="GET"}) @ 1609746000 // INVALID.
範圍向量同樣適用。這將返回在 2021-01-04T07:40:00+00:00 時 http_requests_total 的 5 分鐘速率:
rate(http_requests_total[5m] @ 1609746000)
@ 修飾符支援上述數字字面量的所有表示形式。它與 offset 修飾符配合使用,其中偏移量是相對於 @ 修飾符的時間應用的。無論修飾符的順序如何,結果都是相同的。
例如,這兩個查詢將產生相同的結果:
# offset after @
http_requests_total @ 1609746000 offset 5m
# offset before @
http_requests_total offset 5m @ 1609746000
此外,start() 和 end() 也可以作為 @ 修飾符的特殊值使用。
對於範圍查詢,它們分別解析為範圍查詢的開始和結束時間,並且在所有步長中保持不變。
對於瞬時查詢,start() 和 end() 都解析為評估時間。
http_requests_total @ start()
rate(http_requests_total[5m] @ end())
請注意,@ 修飾符允許查詢提前檢視其評估時間之後的資料。
子查詢
子查詢允許您針對給定的範圍和解析度執行瞬時查詢。子查詢的結果是一個範圍向量。
語法:<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <float_literal> ]
<resolution>是可選的。預設是全域性評估間隔 (evaluation interval)。
運算子
Prometheus 支援許多二元和聚合運算子。這些在 表示式語言運算子 頁面中有詳細描述。
函式
Prometheus 支援多個用於操作資料的函式。這些在 表示式語言函式 頁面中有詳細描述。
註釋
PromQL 支援以 # 開頭的單行註釋。示例:
# This is a comment
正則表示式
Prometheus 中的所有正則表示式都使用 RE2 語法 。
正則表示式匹配始終是完全錨定的。
注意事項
陳舊性
在查詢期間取樣資料的時間戳是獨立於實際存在的時間序列資料而選擇的。這主要是為了支援聚合(例如 sum、avg 等)之類的情況,在這些情況下,多個被聚合的時間序列在時間上並不能精確對齊。由於這種獨立性,Prometheus 需要在這些時間戳上為每個相關的時間序列分配一個值。它透過獲取小於回溯期之前最新的一個樣本來實現。預設情況下,回溯期為 5 分鐘,但可以使用 --query.lookback-delta 標誌進行設定,或者透過 lookback_delta 引數在單個查詢上進行覆蓋。
如果目標抓取或規則評估不再為之前存在的時間序列返回樣本,則該時間序列將被標記為陳舊 (stale)。如果刪除了某個目標,則在刪除後不久,之前獲取的時間序列將被標記為陳舊。
如果在時間序列被標記為陳舊之後的時間戳對查詢進行求值,則不會為該時間序列返回任何值。如果隨後為該時間序列攝取了新樣本,它們將按預期返回。
當時間序列不再被匯出或目標不再存在時,它就會變得陳舊。此類時間序列將在其最後採集的樣本時間點從圖表中消失,並且在標記為陳舊後不會在查詢中返回。
某些將自己的時間戳放在樣本上的 Exporter 會有不同的行為:停止匯出的序列在消失前會採用(預設)5 分鐘的最後一個值。track_timestamps_staleness 設定可以更改此行為。
避免慢查詢和過載
如果查詢需要處理大量資料,對其進行圖表化處理可能會超時,或者使伺服器或瀏覽器過載。因此,在對未知資料構建查詢時,請始終在 Prometheus 表示式瀏覽器的表格檢視中開始構建查詢,直到結果集看起來合理(最多為數百個,而不是數千個時間序列)。只有當您對資料進行了充分的過濾或聚合後,再切換到圖表模式。如果表示式即時生成圖表仍然耗時太長,請透過 記錄規則 (recording rule) 預先記錄它。
這對於 Prometheus 的查詢語言尤為重要,因為像 api_http_requests_total 這樣僅含有指標名稱的選擇器可能會擴充套件為數千個帶有不同標籤的時間序列。另外,請記住,對許多時間序列進行聚合的表示式即使輸出的只是少量時間序列,也會在伺服器上產生負載。這類似於對關係資料庫中某一列的所有值進行求和會很慢,即使輸出值只是一個數字。