本篇先來回答語法以外的問題。
本節的問題有兩個:
除了報警系統響時可以間接得知 Prometheus 裡的資料以外,都是靠 http 來傳資料的。
相關 http API 有:
Prometheus 提供一個定時寫出資料的 http client,主要用來把資料寫到下游的資料庫如 InfluxDB、OpenTSDB、Graphite 或是其他 Prometheus。
只要依文件在設定檔裡設定好 remote_write
,Prometheus 就會把資料寫出去了。
用 API 來讀取時間序資料都會用到 PromQL,PromQL 有四種運算時的中間型態,但能返回的資料型態基本只有一種。就是一個由時間序列所構成的時間序列集。
這個時間序列集可以只有一個時間序列,也可以有多個時間序列。它們都會有對應的標籤值和樣本值。
如 PromQL: api_http_responses
這個時間序列集可能包含了四個時間序列:
api_http_responses{job="apiserver", handler="/api/comments"} # 1 1 3
api_http_responses{job="apiserver", handler="/api/posts"} # 1 2 3
api_http_responses{job="ingested", handler="/api/comments"} # 0 7 12
api_http_responses{job="ingested", handler="/api/posts"} # 2 2 4
從而 PromQL: sum(api_http_responses) by (job)
這個時間序列集包含了兩個時間序列:
{job="apiserver"} # 2 3 6
{job="ingested"} # 2 9 16
瞭解了 PromQL 返回的資料型態,就可以知道讀取資料的 API 拿 PromQL 做些什麼了。
/query
這個 API 一般用來讀取給定時間點下,PromQL 表達的時間序列集中,每個時間序列當時最新的樣本值。參數有:
query
:PromQL 表達式time
:要查詢的時間點(預設是 Prometheus 收到 http 的時間)timeout
:http 超時時限回傳資料格式是 JSON
借用文件的例子:
$ curl 'http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z'
{
"status" : "success",
"data" : {
"resultType" : "vector",
"result" : [
{
"metric" : {
"__name__" : "up",
"job" : "prometheus",
"instance" : "localhost:9090"
},
"value": [ 1435781451.781, "1" ]
},
{
"metric" : {
"__name__" : "up",
"job" : "node",
"instance" : "localhost:9100"
},
"value" : [ 1435781451.781, "0" ]
}
]
}
}
查詢名為 up
的序列集,得兩個時間序列
up{job="prometheus", instance="localhost:9090"}
up{job="node", instance="localhost:9100"}
而這兩個時間序列在查詢時間點的值分別是 1
和 0
。
/query_range
這個 API 是 /query
的加強版,也是 Grafana 監控面版用的 API。它不只查詢某個時間點的值,而是可以對一段時間內的值間隔取樣計算。參數有:
query
:PromQL 表達式start
:取樣時間最小值(閉區間)end
:取樣時間最大值(閉區間)step
:取樣間隔(從 start 開始,每次加 step)timeout
:http 超時時限回傳資料格式是 JSON
$ curl 'http://localhost:9090/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15s'
{
"status" : "success",
"data" : {
"resultType" : "matrix",
"result" : [
{
"metric" : {
"__name__" : "up",
"job" : "prometheus",
"instance" : "localhost:9090"
},
"values" : [
[ 1435781430.781, "1" ],
[ 1435781445.781, "1" ],
[ 1435781460.781, "1" ]
]
},
{
"metric" : {
"__name__" : "up",
"job" : "node",
"instance" : "localhost:9100"
},
"values" : [
[ 1435781430.781, "0" ],
[ 1435781445.781, "0" ],
[ 1435781460.781, "0" ]
]
}
]
}
}
注意到每個樣本值的時間戳記都是 http 所指定的取樣時間,而不是樣本從標的被拉到 Prometheus 的時間。step
越小,樣本值的數量就越多。如果取樣間隔遠小於 Prometheus 拉資料的間隔,回傳的樣本值就會有很多重複的,因為取樣時的樣本值都沒有變。
/query_exemplars
這個 API 類似 /query
,但它查詢的是指標的範例值(OpenMetrics 規定加在註解的部份)。參數有:
query
:PromQL 表達式start
:時間最小值(閉區間)end
:時間最大值(閉區間)這些 API 用來讀取 Prometheus 裡的中介資料,如標籤值、標籤值的值、時間序列集。這些 API 一般用來幫助使用者查詢 Prometheus 裡有哪些時間序列,或是有哪些標籤值。
/series
這個 API 用來查詢 Prometheus 裡有哪些時間序列在給定時間範圍內有值。參數有:
match[]
:時間序列的的過濾條件,可以有多個,符合其中一個就會被返回start
:時間最小值(閉區間)end
:時間最大值(閉區間)limit
:最多返回幾個時間序列回傳的資料格式是 JSON。
/labels
和 /series
類似,這個 API 用來查詢 Prometheus 裡有哪些標籤。參數同上。
不同的是回傳的就只有標籤名字,而不是時間序列集。
/label/<標籤名>/values
這個 API 用來查詢 Prometheus 裡某個標籤名在時間範圍內有哪些值。參數亦同上。
回傳的也只有標籤值。
Grafrana 的標籤選單就是用這個 API 來查詢的。
本節的問題:
在資料不變的情況下,PromQL 所表達的時間序列集是不變的。但這裡的資料是不只是 Prometheus 的存起來的資料,還包含 PromQL 所取樣的時間點。
舉一個極端的例子,如果有一個時間序列 x 在奇數秒的值是 1,偶數秒的值是 0。那麼 PromQL: 1 / x
這個表達式就只有在奇數秒有值。
那麼 query_range?step=2&start=0.5
跟 query_range?step=2&start=1.5
這兩個查詢就會得到不同的結果。query_range?step=2&start=0.5
會得到全部都是 1,而 query_range?step=2&start=1.5
會全部都是 +Inf。