開發一個簡單的golang prometheus exporter.


以下是一個簡單的學習關於golang 開發prometheus exporter 的說明

環境准備

  • go mod
module ladap-exporter
go 1.14
require (
    github.com/go-ldap/ldap/v3 v3.2.3 // indirect
    github.com/prometheus/client_golang v1.7.1
)
 
 
  • main.go
package main
import (
    "flag"
    "net/http"
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)
var addr = flag.String("listen-address", ":9001", "The address to listen on for HTTP requests.")
var rpcDurations = prometheus.NewSummaryVec(
    prometheus.SummaryOpts{
        Name:       "rpc_durations_seconds",
        Help:       "RPC latency distributions.",
        Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
    },
    []string{"service"},
)
var up = prometheus.NewDesc(
    "ldap_up",
    "watch ladap info",
    []string{"name", "class"},
    nil,
)
var rpc = prometheus.NewDesc(
    "rpc_request_total",
    "rpc request total",
    []string{"rpc_func", "rpc_source"},
    nil,
)
var version = prometheus.MustNewConstMetric(
    prometheus.NewDesc("ldap_exporter_version", "ldap exporter version", []string{"type", "build"}, nil),
    prometheus.GaugeValue,
    1.0,
    "cust", "2020-09-08",
)
// MyLDAPCollector myLDAPCollector
type MyLDAPCollector struct {
    up      *prometheus.Desc
    rpc     *prometheus.Desc
    version *prometheus.Desc
}
//Describe describe
func (c MyLDAPCollector) Describe(ch chan<- *prometheus.Desc) {
    ch <- c.up
    ch <- c.rpc
    ch <- c.version
}
//Collect collect
func (c MyLDAPCollector) Collect(ch chan<- prometheus.Metric) {
    upMetrics := prometheus.MustNewConstMetric(up, prometheus.GaugeValue, 1, "dalong", "demo")
    rpcRequest := prometheus.MustNewConstMetric(rpc, prometheus.CounterValue, 1000, "login", "a")
    ch <- version
    ch <- upMetrics
    ch <- rpcRequest
}
func init() {
    myLDAPCollector := MyLDAPCollector{
        up:      up,
        rpc:     rpc,
        version: version.Desc(),
    }
    // Add MyCus Collector
    prometheus.MustRegister(myLDAPCollector)
    // Add rpc summary collector
    prometheus.MustRegister(rpcDurations)
    // Add Go module build info.
    prometheus.MustRegister(prometheus.NewBuildInfoCollector())
}
func main() {
    flag.Parse()
    server := http.NewServeMux()
    server.HandleFunc("/", func(response http.ResponseWriter, Request *http.Request) {
        indexpage := `<html>
                <body>
                   <h1>ldap exporter</h1>
                   <p><a href="/metrics">metrics</a></p>
                </body>
          </html>`
        response.Write([]byte(indexpage))
    })
    server.HandleFunc("/api", func(response http.ResponseWriter, Request *http.Request) {
        rpcDurations.WithLabelValues("mydemo").Observe(22)
        response.Write([]byte("dalongdemo"))
    })
    server.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(*addr, server)
}
 
  • 代碼說明
    以上代碼同時包含了基於自定義collector 以及內置默認的處理,對於自定義的collector 我們需要實現
    參考接口定義
 
type Collector interface {
    // Describe sends the super-set of all possible descriptors of metrics
    // collected by this Collector to the provided channel and returns once
    // the last descriptor has been sent. The sent descriptors fulfill the
    // consistency and uniqueness requirements described in the Desc
    // documentation.
    //
    // It is valid if one and the same Collector sends duplicate
    // descriptors. Those duplicates are simply ignored. However, two
    // different Collectors must not send duplicate descriptors.
    //
    // Sending no descriptor at all marks the Collector as “unchecked”,
    // i.e. no checks will be performed at registration time, and the
    // Collector may yield any Metric it sees fit in its Collect method.
    //
    // This method idempotently sends the same descriptors throughout the
    // lifetime of the Collector. It may be called concurrently and
    // therefore must be implemented in a concurrency safe way.
    //
    // If a Collector encounters an error while executing this method, it
    // must send an invalid descriptor (created with NewInvalidDesc) to
    // signal the error to the registry.
    Describe(chan<- *Desc)
    // Collect is called by the Prometheus registry when collecting
    // metrics. The implementation sends each collected metric via the
    // provided channel and returns once the last metric has been sent. The
    // descriptor of each sent metric is one of those returned by Describe
    // (unless the Collector is unchecked, see above). Returned metrics that
    // share the same descriptor must differ in their variable label
    // values.
    //
    // This method may be called concurrently and must therefore be
    // implemented in a concurrency safe way. Blocking occurs at the expense
    // of total performance of rendering all registered metrics. Ideally,
    // Collector implementations support concurrent readers.
    Collect(chan<- Metric)
}

type MyLDAPCollector struct 說明
為了方便統計添加了up version 以及rpc 的定義,up 是標記exporter 運行准備的,version 記錄exporter 版本的
rpc 是一個簡單的total 模式的metrics 定義
對於golang prometheus metrics 的定義,一般我們需要的是desc(表明metrics 的名稱,幫助信息,以及可能包含的label)
自定義collector 的Describe主要是進行metrics desc 信息的暴露,Collect 是實際的metrics 處理(拉取數據庫,其他中間件的信息拉取。。。。)
定義完collector之后我們需要進行注冊才能使用,具體的注冊比較簡單prometheus.MustRegister 就可以了,同時golang 版本的sdk
已經提供了好多便捷的metrics 幫助沒(count,gauge.summary,histogram)都是比較方便的,同時也內置了一些golang runtime 的metrics
都是可以注冊使用的
prometheus exporter http server 的暴露也比較簡單,默認以及提供了http handler 的實現,我們注冊就可以了

 
server.Handle("/metrics", promhttp.Handler())
  • 運行效果

go run main.go

 

 

說明

以上是一個簡單的metrics 實現,而且好多語言的框架已經提供了類似的中間件擴展我們可以直接使用

參考資料

https://github.com/prometheus/client_golang


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM