iT邦幫忙

2024 iThome 鐵人賽

DAY 8
1
DevOps

時間序列資料庫探討 - Prometheus系列 第 8

Prometheus - PromQL 語法基本

  • 分享至 

  • xImage
  •  

前篇提問

  • Prometheus 提供了哪些讀介面?
  • PromQL 表達式有哪些語法?如何運行?
  • Alert Template 有哪些語法?

本篇要來介紹 PromQL。

PromQL 的資料型態

先複習一下,Prometheus 資料庫裡我們唯一關心的資料型態是「時間序列」。
一個時間序列的組成包含:

  • 指標名稱 (字串)
  • 指標標籤集
    • 標籤名(字串)
    • 標籤值(字串)
  • 樣本集
    • 浮點數值(float64)
    • 時間戳(毫秒)

至於 PromQL,是要分析這些時間序列。對它們拆裝組合過程中當然就需更多資料型態以利操作。
PromQL 表達式有四種型態:

  • 瞬時向量(Instant Vector)
  • 區間向量(Range Vector)
  • 純量(Scalar)

瞬時向量

瞬時向量是一個時間序列集,在一個特定時間點的的數值。每個時間序列都有一個標籤集和樣本值。

例如

api_http_responses

可能是一個瞬時向量,包含四個時間序列(維度):

# 2015-07-01T20:10:51.781Z
api_http_responses{job="apiserver", handler="/api/comments"} # 1.0
api_http_responses{job="apiserver", handler="/api/posts"} # 2.0
api_http_responses{job="ingested", handler="/api/comments"} # 7.0
api_http_responses{job="ingested", handler="/api/posts"} # 2.0

瞬時向量之間可以做四則運算,例如:

api_http_responses / api_http_requests

四則運算的方式是對相同維度(標籤集)的值一一做四則運算。如果兩個瞬時向量(時間序列集)的維度(標籤集)剛好一一對應。那算出來的新瞬時向量的維度也會一一對應。比方如上可能算出

# 2015-07-01T20:10:51.781Z
{job="apiserver", handler="/api/comments"} # 1.0
{job="apiserver", handler="/api/posts"} # 0.5
{job="ingested", handler="/api/comments"} # 1.0
{job="ingested", handler="/api/posts"} # 1.0

區間向量

區間向量是一個時間序列集,在一個時間區間的樣本集。每個時間序列都有一個標籤集和樣本集。有別於瞬時向量,這裡每個時間序列的樣本集數量不盡相同,時間戳也不需相同。
例如

api_http_responses[1m]

可能是一個一分鐘長的區間向量,包含四個時間序列(維度):

# 2015-07-01T20:10:51.781Z
api_http_responses{job="apiserver", handler="/api/comments"} # (1435781440.723 1.0) (1435781445.029 1.0) (1435781451.781 3.0)
api_http_responses{job="apiserver", handler="/api/posts"} # (1435781423.103 1.0) (1435781431.028 2.0) (1435781451.781 3.0)
api_http_responses{job="ingested", handler="/api/comments"} # (1435781446.135 0.0) (1435781450.971 7.0) (1435781451.781 12.0)
api_http_responses{job="ingested", handler="/api/posts"} # (1435781391.781 2.0) (1435781451.781 4.0)    

區間向量之間不能做四則運算(樣本時間戳對不起來),只能餵給函數變成瞬時向量。最常見的函數應該是irate,用以計算樣本的時間變化率比方:

irate(api_http_responses[1m])

這樣就可以得到一個瞬時向量,包含四個維度:

# 2015-07-01T20:10:51.781Z
{job="apiserver", handler="/api/comments"} # 0.180865
{job="apiserver", handler="/api/posts"} # 0.0697399
{job="ingested", handler="/api/comments"} # 2.12540
{job="ingested", handler="/api/posts"} # 0.0333333

純量

一個浮點數值,例如

1.0
+Inf
1e-6
NaN

可用來做四則運算,例如

(1.0 + 2.0) * api_http_responses

會對每一個維度一一做四則運算。

字串

PromQL 有字串和正則表達式,但是只能用在標籤名和標籤值上。目前沒有函數會吃吐字串。

PromQL 的語法

時間序列選取器

PromQL 做為一個表達式語言,最簡單的語句就是從整個資料庫中選取一些時間序列。
例如以下語句就是選取了所有名為 api_http_response 的時間序列:

api_http_responses

那當我們只想要選取部名為 api_http_response 的時間序列時該怎麼辦呢?我們可以在隨後的大括號裡面加上選取的條件。例如選取 job 標籤值不為 ingested ,且 handler 標籤為 s 結尾的時間序列:

api_http_responses{job!="ingested", handler=~".*s"}

會得到以下時間序列:

# 2015-07-01T20:10:51.781Z
api_http_responses{job="apiserver", handler="/api/comments"} # 1.0
api_http_responses{job="apiserver", handler="/api/posts"} # 2.0

這邊說明一下,我們展開運算結果,以及標的 http 資料,也是大括號跟在指標名稱後面。但在運算結果和標的 http 資料中,大括號裡面的東西是標籤集,只能有等號,且需窮舉所有標籤。而在 PromQL 語句中,大括號裡面的東西是選取器,裡面放的是條件。

區間向量選取器

區間向量選取器非常類間單,就是在時間序列選取器後面加上中括號,裡面放上時間窗口大小。例如

api_http_responses[1m]
api_http_responses{job!="ingested", handler=~".*s"}[1d]

重點是我們只能對時間序列選取器加上中括號,不能對其他瞬時向量加中括號,因為瞬時向量並沒有原始的樣本資訊,只有單一時間的的數值。
有趣的是從某個 Prometheus 版本開始,時間區間就從閉區間變成左開右閉了…

PromQL 的關鍵字

PromQL 有許多運算子,這裡列出一些常見的:

  • +-*/%^:五則運算和次方運算
  • == != > < >= <=:比較運算
  • and or unless:邏輯運算
  • on ignoring group_left group_right:分組運算

五則、次方、邏輯運算

他們都是二元運算子,對瞬時向量和純量運算。原則上就是對瞬時向量的每個維度一一運算。

分組運算

分組運算是用來調整標籤集的,為了讓兩個標籤不同的瞬時向量做運算。例如

cpu_usage / on(job) api_http_requests

這樣只會保留對 job 標籤值相同的維度一一做加法運算。

PromQL 的函數

詳見文件。每個函數的都有參數個回傳都有固定型態。這裡列出一些常見的:

  • rate
    • 外插時間窗口左界的樣本值,然後計算時間窗口內的平均變化率
  • irate
    • 取時間窗口內最右邊的兩個樣本,計算兩樣本間的平均時間變化率
  • sum
  • avg
  • max
  • topk
  • histogram_quantile
  • histogram_quantile_over_time

上一篇
Prometheus - 讀取時間序列資料的 API
下一篇
Prometheus - 警報規則和模板
系列文
時間序列資料庫探討 - Prometheus13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言