本篇要來回答寫入介面相關的兩個問題。
Prometheus Client 函式庫主要是實作一個 http handler,提供 /metrics
。這個 http handler 會有一個登錄表(Registry),可以登錄許多 Collector(不同型態的指標)。這個 handler 做得事情就是把登錄表裡的所有指標資料的值串接起來,回傳給 Prometheus。
由於 python 有各種 GIL 和 Singleton 我們看不到一些預設參數,不適合用於舉例,所以這裡用官方文件的 Go 範例來說明。
建立一個沒有任何指標的 http handler:
package main
import (
"net/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func main() {
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":2112", nil)
}
其中 promhttp.Handler()
內是
func Handler() http.Handler {
return InstrumentMetricHandler(
prometheus.DefaultRegisterer, HandlerFor(prometheus.DefaultGatherer, HandlerOpts{}),
)
}
有一個 DefaultRegisterer
就是預設的登錄表。
之後登錄在 DefaultRegisterer
下的 Collector(Counter, Gauge, Histogram, Summary)指標變化就會反應在 http response 裡。
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func recordMetrics() {
go func() {
for {
opsProcessed.Inc()
time.Sleep(2 * time.Second)
}
}()
}
var (
opsProcessed = promauto.NewCounter(prometheus.CounterOpts{
Name: "myapp_processed_ops_total",
Help: "The total number of processed events",
})
)
func main() {
recordMetrics()
http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":2112", nil)
}
這樣就可以在 http://localhost:2112/metrics
看到指標資料了。
Golang 的 Prometheus Client 提供四種 Collector(相當於指標族)型態,能夠:
Inc()
:增加 1。Add(float64)
:增加指定數值。Inc()
:增加 1。Dec()
:減少 1。Add(float64)
:增加指定數值。Sub(float64)
:減少指定數值。Set(float64)
:設定為指定數值。SetToCurrentTime()
:設定為當前時間。Observe(float64)
:記錄一個樣本。Observe(float64)
:記錄一個樣本。Prometheus Client 函式庫對資料一致性的要求高。比方 Counter,如果在多執行緒的環境下,有兩個執行緒同時執行 Inc()
的情況下,我們得保證最後的值是增加 2。
一致性的要求不只體現在寫資料時,也體現在讀資料時。比方 Histogram,Observe(1)
發生時,le="1"
和le="2"
的值都要增加。不能在 le="1"
增加、但 le="2"
未增加時,就把 le="1"
和 le="2"
的值讀出來。
資料一致性是由 Collector 實作負責保證的。比方 Counter 就是使用 atomic 函式庫來處理讀寫。Summary 則是使用 RWMutex 和 hot-cold buffer 來維持讀寫的效能,免得若是同時有很多 http request 進來,一直鎖著 RMutex ,導致寫入和計算百分位數的效能下降。
PushGateway 是一個做為指標暫存的服務。當 Prometheus 拉取資料的時間間隔太長,或是標的的生命週期太短,來不及拉,就可以讓標的把指標資料推給 PushGateway 暫存。之後 Prometheus 再定時從 PushGateway 拉取資料。
PushGateway 和 Prometheus 是兩支不同程式,預設分別佔用 :9090 和 :9091。
PushGateway 的使用方式很簡單,只要把指標資料推送到 /metrics/job/<job>
端點即可。其中 <job>
是一個標識符,用來區分不同的標的,需由推送者自行報告。之所以需要這個標識符,是因為 Prometheus 從 PushGateway 拉取資料時,會拉到所有不同來源推到 PushGateway 的指標,並以為它們來自同一標的。為了區分這些來源,就需要這個標識符。
推送指標到 http 的方式有 PUT 和 POST 兩種。
用 PUT 推送會把所有同 job 的指標資料覆蓋,就好像 job 被重新啟動一樣。這樣做的好處是可以避免指標資料的累積,但是也可能會造成資料遺失。
反之用 POST 推送會把指標資料加到原本的資料上,這樣做的好處是可以避免資料遺失。
推送的指標資料格式和 Prometheus 拉資料的 http response 一樣,只是多了一個 job
標籤。
另一個一樣的地方是,prometheus client 函式庫提供的指標族,也可以推送指標。所以我們其實不需要知道推送的指標資料格式,只要用 prometheus client 函式庫提供推送 Registry 的介面就夠了。