詳解Prometheus range query中的step參數

GH Page地址git

Prometheus有兩種query:instant queryrange query。本文要講的就是range query中的step參數。github

range query是很是常見的一種query,看看它有哪些參數:express

  • query=<string>: PromQL表達式。
  • start=<rfc3339 | unix_timestamp>: 時間範圍的開始。
  • end=<rfc3339 | unix_timestamp>: 時間範圍的結束。
  • step=<duration | float>: 查詢解析度(query resolution)。
  • timeout=<duration>: 執行超時。這個參數是可選的。

在Prometheus expression browser裏看到的是這樣的:segmentfault

clipboard.png

注意到上圖中的Res框裏沒有給值,沒有給的話Prometheus會自動給一個值,這個值在圖示右上角能夠看到。api

step對於查詢結果的影響

Prometheues在對PromQL表達式求值的邏輯是這樣的(詳見這個issue裏的回答):bash

  1. 對於[start, end]時間區間,從start開始,以step爲長度,把時間區間分紅若干段
  2. 對每一個段進行求值

舉例:start=10,end=20,step=2,那麼就會有ts=10,ts=12,ts=14,ts=16,ts=18,ts=206段,而後爲這6個段進行求值。求值方式視乎表達式中Time series selector的類型而定。post

PromQL有兩種Time series selector:instant vector selectorrange vector selector。下面將分別講解:spa

Instant vector selector

形以下面的就是Instant vector selector,x是metric的名字。unix

x

Prometheus在對每段Instant vector selector求值的邏輯是這樣的:code

  • 從該段的timestamp(含)往前找,取第一個找到的data point的值。若是有一個data point的timestamp==該段的timestamp,則直接使用該data point。
  • 若是該段timestamp往前的5分鐘範圍內沒有找到任何data point,則該段無值。

下面這張圖解釋了上面邏輯:

clipboard.png

圖中的綠點是Prometheus實際存儲的數據,按照時間軸從左到右排列。藍點是根據step參數的求值結果。

當data point間隔比step更大的時候會發生下圖這種狀況:

clipboard.png

能夠看到有兩個段的求值結果來自於同一個data point。

Range vector selector

形以下面的就是Range vector selector,x是metric的名字,方括號裏的是range duration

x[5m]

range vector select返回的是當前timestamp以前的range duration內的全部data point。range vector是不能直接用作繪圖的,你得用某些function把range vector轉換成instant vector才行,好比rate()

下圖解釋了是如何對Range vector selector進行分段求值的:

clipboard.png

step和rate duration

steprange duration是獨立的兩個參數,在某些狀況下二者的值存在某種限制條件,這裏例舉rate()來講明。rate()的做用是得到一個range-vector的每秒平均增加率。

若是step=10mrange duration=5m,那麼rate在計算的時候會丟失一半的數據,兩個分段之間的data point有一半沒有被歸入計算。前面那張圖就存在數據丟失的狀況,有一個data point被漏掉了。

所以在使用rate()時,range duration得大於等於step

而若是是irate(),這個限制則是range duration不得大於step(詳見Brian Brazil的Presentation)。

Grafana中的step參數

在Grafana中並無直接提供step參數,而是這兩個參數:min stepresolution文檔在這裏)。min step故名思義設定的是step的最小值,那麼resolution是什麼呢?

你們都知道Grafana都是用來畫圖的,好比下面這張圖Y軸是值,X軸則是時間線,所以在X軸方向的每一個像素都表明了一個timestamp。

clipboard.png

resolution就是用來根據像素來計算step的一個參數。下面用6個像素以及它們的timestamp來講明:

x=1,ts=0; x=2,ts=5; x=3,ts=10; x=4,ts=15; x=5,ts=20; x=6,ts=25
  • resolution=1/1時,那麼step就是相鄰像素所表明的timestamp的差,即5;
  • resolution=1/2時,那麼step就是相隔1個像素的兩個像素的timestamp的差,即10;
  • resolution=1/3時,那麼step就是相隔2個像素的兩個像素的timestamp的差,即15;
  • 以此類推

而每一個像素所表明的timestamp受兩個因素影響:

  1. 查詢所定義的時間範圍
  2. Graph的寬度(單位:像素)

因此在Grafana發起的查詢中step參數是動態的。其實這也是很合理的,由於只有這樣纔可以在Graph寬度小的時候繪圖更粗糙(即step更大),Graph寬度大的時候繪圖更精細(即step更小,可是不能小於min step)。實際發起的請求的step參數你能夠在Graph的Query Inspector裏看到:

clipboard.png

可是咱們以前不說過了rate()range duration不能小於step嗎?那麼把range duration給固定值的化就不太好了,怎麼辦呢?你可使用Grafana提供的內置變量$__interval,它表明的Grafana就是計算出來的step的值。好比這樣就可以將range durationstep保持一致了(更多內置變量能夠見這裏):

rate(x[$__interval])

因此,你想本身實驗一把

若是你想本身動手實驗,可是又苦於沒法制造乾淨的假數據,那麼能夠參考這篇文章推薦的方法

相關文章
相關標籤/搜索