用 Golang 實作 Prometheus:服務效能測量監控系統

Prometheus 是一個基於 Golang 語言所撰寫的服務效能測量監控系統。實際上就只是把統計數據視覺化而已,這很適合用在大型系統、微服務上。你可以從 Prometheus 查看你所有服務的效能狀態等。

但這些事情可能沒有你想像的那麼自動,因為有些數據的加總、值的異動都需要自行在程式裡面處理,然後 Prometheus 會向你的程式要求這些資料。

1. 安裝與啟動 Prometheus

Prometheus 這個單字好像有點難記,我自己是切分成「Prome-th-eus」來記。廢話不多說,首先進入 Prometheus 的下載頁面,接著選取符合你系統的壓縮或安裝檔。

接著解壓縮,然後在解壓縮的目錄會看見 prometheus.yml 設定檔,打開之後找到下列段落。

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.

static_configs:  
    - targets: ['localhost:9090']

改成下列這樣。

# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.

static_configs:  
    - targets: ['localhost:9090', 'localhost:8080']

儲存檔案接著在同個目錄中以下列指令執行 prometheus 檔案即可啟動 Prometheus。

$ ./prometheus

接著就能夠看到像下面這樣執行的介面。

2. 網頁管理介面

現在進入 http://localhost:9090/ 你就可以直接看到 Prometheus 的網頁介面(又是 Bootstrap,耶!)

接著在 - insert metric at cursor - 下拉式選單中查看你要看的統計數據,接著按下左側的 Graph 分頁就能夠看到圖表統計了。

到這裡就沒了,我們目前能夠看到的圖表數據都是來自 Prometheus 系統內的數據。接下來就是要實作從 Golang 中將數據帶到 Prometheus 中,如此一來我們就能夠在 Prometheus 裡觀察我們的程式。

3. 引用套件庫

在這裡我們會用到 client_golang 套件。在終端機中透過 go get 指令取得。

$ go get github.com/prometheus/client_golang/prometheus

接著在你的程式中引用該套件。

import (  
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp" 
)

4. 實作數據測量程式

接著我們要實作一個能夠暴露測量數據給 Prometheus 的程式,讓我們假設這個程式會提供兩個測量數據:cpu_temperature_celsiushd_errors_total

一個是 CPU 溫度,另一個則是硬碟錯誤次數,而這個錯誤次數還順便帶有了「裝置」標籤,這意味著我們可以詳細地告訴 Prometheus 這個錯誤次數是哪個「裝置」所發生的。

package main

import (  
    "net/http"
    "log"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var (  
    // 自訂數值型態的測量數據。
    cpuTemp = prometheus.NewGauge(prometheus.GaugeOpts{
        Name: "cpu_temperature_celsius",
        Help: "CPU 目前的溫度。",
    })
    // 計數型態的測量數據,並帶有自訂標籤。
    hdFailures = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "hd_errors_total",
            Help: "硬碟發生錯誤的次數。",
        },
        []string{"裝置"},
    )
)

func init() {  
    // 測量數據必須註冊才會暴露給外界知道:
    prometheus.MustRegister(cpuTemp)
    prometheus.MustRegister(hdFailures)
}

func main() {  
    // 配置測量數據的數值。
    cpuTemp.Set(65.3)
    hdFailures.With(prometheus.Labels{"裝置":"/dev/sda"}).Inc()

    // 我們會用 Prometheus 所提供的預設處理函式在 "/metrics" 路徑監控著。
    // 這會暴露我們的數據內容,所以 Prometheus 就能夠獲取這些數據。
    http.Handle("/metrics", promhttp.Handler())
    log.Fatal(http.ListenAndServe(":8080", nil))
}

現在透過 go run 執行這段程式,然後回到網頁介面看看一些數據是不是就變成有兩個來源了呢?

如果你仍不確定,你可以從上方的 Status 下拉式選單選取 Targets 然後就可以看見 Prometheus 是否有正常的在監控你的程式。