Prometheus2.0 的查詢 DSL

Prometheus 的查詢有一套專用語言,叫做 PromQL。其表達式可能是受了 golang 的影響,非常的緊湊和符號化。這使得其易於書寫但難以理解(對不熟悉這種 DSL 的人來說)。因而有了這篇文章。

以下內容基於官方文檔(2.0)編譯。

數據類型

表達式的值一定屬於以下四種數據類型其一:

  • 瞬時向量(Instant Vector)一組時序數據。其中每個時序都只有一個時間點,且一組數據的該時間點相同,比如今天 12:05:30 時所有服務器的 CPU 負載。
  • 範圍向量(Range Vector)一組時序數據,但每個時序都有一段時間的採樣點。
  • 標量(Scalar)單純的浮點數
  • 字符串(String)單純的字符串(暫未使用)

向量和標量的區別僅在於向量是來自於時序數據的一個採樣點,因此其帶有時間戳、metric、labels 等屬性。

我們主要關注兩種向量的區別。從字面上來看,也許會覺得,畫圖(如 /graph)用的是範圍向量,因爲畫圖就是畫的時序在一段時間範圍內採樣的值嘛。但其實能夠用來畫圖的只有 瞬時向量。Prometheus 的運算邏輯是這樣的:表達式只是返回一次計算的值,當畫圖的時候,先把總的時間段分割(downsample),然後分別計算每段上的瞬時向量,並賦予該時間段的起始時間戳。最後所有的段連接起來就是一張圖。有點像 map/reduce 的過程。

字面量

字面量是最簡單的一種表達式,所見即所得。但也有一些需要注意的地方,比如字符串。

單引號和雙引號作用類似,使用 "\" 來進行轉義。反引號括起來的字符串則完全不進行轉義。其轉義規則與 golang 相同。

時序查詢語句

瞬時向量查詢

即選取(select)一組時序數據的語句,是表達式的基本語句。從到現在的描述可以看出,PromeQL 並不明確區分一條一組時序數據。可能在它的邏輯裏這兩者的本質是一樣的,一條不過是一組的一個特例而已。

最簡單的語句是一個 metric 名稱

http_requests_total

然後可以加一些過濾條件(label)

http_requests_total{job="prometheus",group="canary"}

label 運算也支持除 = 外的其他運算符號,比如 != 不等於;=~ 正則匹配;!~正則不匹配。如

http_requests_total{environment=~"staging|testing|development",method!="GET"}

匹配運算有一個特殊問題就是如何處理空值。Prometheus 的方式是,key=""這種可以匹配不包含該 key 的時序,而 key=~'.*' 這種同樣支持空值的正則表達式則只匹配包含該 key 的時序。

Prome 比較有趣的地方是支持不包含 metric 的查詢語句,前提是至少有一個 label 不匹配空值,即避免 select all

{job=~".+"} # Good!
{job=~".*"} # Bad!

更有趣的地方是,這種 label 匹配語句還可以匹配 metric 的名字,通過使用 __name__ 這個內置變量:

{__name__=~"^http.*"}

範圍向量查詢

範圍向量的查詢語法就是在瞬時向量的後面加一個 [] 標識從該瞬時向量的時間戳起向前選取多久的時間範圍。中括號內支持一系列的形如 \d+\s的時間段表達式,表達式單位從小到大包含

  • s
  • m
  • h
  • d
  • w
  • y

注意裏面沒有。一個主要的原因可能是月並非一個明確的時間段,另一個原因可能是和分鐘的首字母衝突。雖然可以用大寫 M 代替,但結合理由一,似乎引入這個單位帶來的麻煩比好處要多。

offset 修飾符

用來將查詢語句向更早平移的修飾符,可以修飾兩種向量。使用時需注意一定要緊貼查詢語句,如瞬時向量:

sum(http_requests_total{method="GET"} offset 5m) // GOOD.
sum(http_requests_total{method="GET"}) offset 5m // INVALID.

亦如範圍向量

rate(http_requests_total[5m] offset 1w)

運算符

像剛展示的 sum, rate 等,PromeQL 支持很多二元或聚合運算符。他們的詳細描述可以參考:OPERATORS

聚合

提供一個分組 label 和一個運算方法,如:以 job 分組,每組qps求和:

sum(rate(http_requests_total[5m])) by (job)

運算

如果兩個 metric 的 label 完全匹配,那麼他們之間就可以進行四則運算,比如減法:

(instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024

回到瞬時向量和範圍向量上,可以看到運算符的運算過程是可以轉化這兩種向量的。比如最簡單的 sum,可以把一個範圍向量加和成爲一個瞬時向量。這樣你在 /graph 裏不能展示的 http_requests_total[5m] 在套上一個 sum 後就可以畫圖了。

還有一個要注意的問題是 ratesum 搭配的時候要注意順序:rate-then-sum-never-sum-then-rate

因爲運算符的種類細節並不影響對 PromeQL 的理解,所以這裏直接跳過。

函數

同上,參考:FUNCTIONS

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章