PromQL 引擎將 PromQL 解析成語法樹後,會載入需要的時間序列 Series
以取得樣本值的迭代器。
本篇將以下列 PromQL 語句為例,說明 PromQL 引擎如何運用迭代器來計算結果。
topk(2, sum(rate(container_cpu_usage_seconds_total[5m] / machine_cpu_cores) * 100) by (name))
範例查詢語句中,container_cpu_usage_seconds_total[5m]
會產生一個 5 分鐘的窗口。PromQL 引擎會確保 container_cpu_usage_seconds_total
載入的樣本時間範圍有涵蓋所有窗口。
而此時 PromQL 引擎並不會把每個樣本時間的窗口全部展開,這樣會佔據太多記憶體。而是只記錄窗口的大小,並在需要時再展開。
範例查詢語句中,rate
是估算時間窗口內的數值增加率。計算時是逐 Series
逐樣本點進行的。如
{container="foo"} # 1728489600
{container="foo"} # 1728489615
{container="foo"} # 1728489630
...
{container="bar"} # 1728489600
{container="bar"} # 1728489615
{container="bar"} # 1728489630
...
每計算一個點時,都要輸入 container_cpu_usage_seconds_total
在 5 分鐘窗口內所有樣本值。PromQL 引擎的做法是只維護一個數值陣列,裡面存於窗口內的樣本值。每次要計算下個樣本點時,把陣列內太舊的樣本值移除,並加入新的樣本值。更動完陣列後才呼叫 rate
函數。
範例查詢語句中的除法。PromQL 會載入左右兩邊的 Series
集,並以標籤集配對。確定兩邊的序列一一對應後,再逐對展開計算所有樣本值。
topk(2, sum(rate(container_cpu_usage_seconds_total[5m] / machine_cpu_cores) * 100) by (name))
上述查詢語句中的 sum 和 topk。PromQL 引擎運算時,會將每個輸入 Series
映射到一個輸出標籤集。例如:
sum by name:
{name="foo", container_index="1"} -> {name="foo"}
{name="foo", container_index="2"} -> {name="foo"}
{name="bar", container_index="1"} -> {name="bar"}
{name="bar", container_index="2"} -> {name="bar"}
topk:
{name="foo"} -> {}
{name="bar"} -> {}
接著讀取所有輸入的的樣本值,計入對應的資料結構中。
sum 就是把樣本點加到對應的陣列項上。而 topk 則是每個輸出標籤集的每個抽樣時間點都有一個大小為 k 的 heap。PromQL 引擎會將每個樣本點放入對應的 heap 中,最後再從每個抽樣時間點的 heap 中取出前 k 個樣本點,組成新的 Series
並回傳。