刘总的笔记小站

生活常识,娱乐搞笑,编程技巧,智能家居,深度学习,网络神经,数据挖掘

实现一个prometheus的exporter示例

实现一个prometheus的exporter示例

1,必须启动prometheus(prometheus以客户端的模式运行,然后自动周期去prometheus.yml中配置的exporter拉取数据),配置 prometheus.yml中exporter对应的promhttp的IP和端口,如果有改动配置文件,重启下prometheus程序;

2,启动自己的exporter,访问自己的exporter端口以及prometheus的task列表,都会有状态和数据变化。

3,启动grafana-6.7.6监控面板,配置数据源以及图标,即prometheus的exporter,就可以显示仪表盘。


开发exporter示例,Counter (累加指标)    Gauge (测量指标)    Summary (概略图)    Histogram (直方图)


示例:

package main

import (
    "fmt"
    "net/http"
)

func HelloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "lexporter_request_count{user=\"admin\"} 1000" )
}

func main () {
    http.HandleFunc("/metrics", HelloHandler)
    http.ListenAndServe(":8000", nil)
}


基本:

package main

import (
    "fmt"
    "net/http"
    "runtime"
    "strings"
    "sync"
    "time"

    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/collectors"
    "github.com/prometheus/client_golang/prometheus/promhttp"
    "github.com/prometheus/common/promlog"
    "github.com/prometheus/common/version"

    "github.com/go-kit/log"
    "github.com/go-kit/log/level"
)

//var exporter = struct {
//    Name string
//    Type string
//}{"terminal", "exporter"}

var exporter = []string{"terminal", "exporter"}

type nodeStatsMetrics []struct {
    desc    *prometheus.Desc
    eval    func(*runtime.MemStats) float64
    valType prometheus.ValueType
}

type NodeCollector struct {
    counterDesc   *prometheus.Desc //Counter
    hybridMetrics nodeStatsMetrics //hybrid
    gaugeDesc     *prometheus.Desc //Gauge
    summaryDesc   *prometheus.Desc //summary
    histogramDesc *prometheus.Desc //histogram
    mutex         sync.Mutex
}

func NewNodeCollector() prometheus.Collector {

    return &NodeCollector{
        counterDesc: prometheus.NewDesc(
            strings.Join(exporter, "_")+"_counter_desc",
            "terminal exporter counter desc",
            []string{"DYNAMIC_GOOS_NAME"},
            prometheus.Labels{"STATIC_LABEL": "STATIC VALUE HERE", "GOOS": runtime.GOOS}),
        hybridMetrics: nodeStatsMetrics{
            {
                desc: prometheus.NewDesc(
                    strings.Join(exporter, "_")+"_mem_total",
                    "terminal exporter ms.Sys",
                    nil, nil),
                valType: prometheus.GaugeValue,
                eval:    func(ms *runtime.MemStats) float64 { return float64(ms.Sys) / 1e9 },
            },
            {
                desc: prometheus.NewDesc(
                    strings.Join(exporter, "_")+"_mem_heap",
                    "terminal exporter ms.HeapSys",
                    nil, nil),
                valType: prometheus.GaugeValue,
                eval:    func(ms *runtime.MemStats) float64 { return float64(ms.HeapSys) / 1e9 },
            },
        },
        gaugeDesc: prometheus.NewDesc(
            strings.Join(exporter, "_")+"_gauge_desc",
            "terminal exporter gaugeDesc",
            []string{"gauge"}, nil),
        summaryDesc: prometheus.NewDesc(
            strings.Join(exporter, "_")+"_summary_desc",
            "terminal exporter summaryDesc",
            []string{"code", "method"},
            prometheus.Labels{"owner": "example"},
        ),
        histogramDesc: prometheus.NewDesc(
            strings.Join(exporter, "_")+"_histogram_desc",
            "terminal exporter histogramDesc",
            []string{"code", "method"},
            prometheus.Labels{"owner": "example"},
        ),
    }
}

// Describe returns all descriptions of the collector.
func (n *NodeCollector) Describe(ch chan<- *prometheus.Desc) {
    ch <- n.counterDesc
    for _, metric := range n.hybridMetrics {
        ch <- metric.desc
    }
    ch <- n.gaugeDesc
    ch <- n.summaryDesc
    ch <- n.histogramDesc
}

// Collect returns the current state of all metrics of the collector.
func (n *NodeCollector) Collect(ch chan<- prometheus.Metric) {

    n.mutex.Lock()

    ch <- prometheus.MustNewConstMetric(n.counterDesc, prometheus.CounterValue, 0, runtime.GOOS)
    vm := &runtime.MemStats{}
    for _, metric := range n.hybridMetrics {
        ch <- prometheus.MustNewConstMetric(metric.desc, metric.valType, metric.eval(vm))
    }

    num, _ := runtime.ThreadCreateProfile(nil)
    ch <- prometheus.MustNewConstMetric(n.gaugeDesc, prometheus.GaugeValue, float64(num), "thread", )
    ch <- prometheus.MustNewConstMetric(n.gaugeDesc, prometheus.GaugeValue, float64(runtime.NumGoroutine()), "num")

    ch <- prometheus.MustNewConstSummary(
        n.summaryDesc,
        4711, 403.34,
        map[float64]float64{0.5: 42.3, 0.9: 323.3},
        "200", "get",
    )
    ch <- prometheus.MustNewConstHistogram(
        n.histogramDesc,
        4711, 403.34,
        map[float64]uint64{25: 121, 50: 2403, 100: 3221, 200: 4233},
        "200", "get",
    )

    n.mutex.Unlock()

}

var promRegistry = prometheus.NewRegistry()
var promCounter = prometheus.NewCounter(
    prometheus.CounterOpts{
        Name: "terminal_exporter_counter",
        Help: "Current terminal exporter counter.",
    },
)

var promGauge = prometheus.NewGauge(
    prometheus.GaugeOpts{
        Name: "terminal_exporter_gauge",
        Help: "Unix timestamp of the last received metrics push in seconds.",
    },
)

var promTotal = prometheus.NewCounterVec(
    prometheus.CounterOpts{
        Name: "terminal_exporter_total",
        Help: "Current terminal exporter total.",
    },
    []string{"terminal"},
)

func init() {
    promRegistry.MustRegister(
        collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}),
        collectors.NewGoCollector(),
        collectors.NewBuildInfoCollector(),
    )
    promRegistry.MustRegister(version.NewCollector("terminal_exporter"))
    promRegistry.MustRegister(promCounter)
    promRegistry.MustRegister(promGauge)
    promRegistry.MustRegister(promTotal)

    promRegistry.MustRegister(NewNodeCollector())

    promGauge.Set(6.4)
    promCounter.Add(1)

    promTotal.With(prometheus.Labels{"terminal": "device"}).Add(5)
    promTotal.With(prometheus.Labels{"terminal": "device"}).Inc()
    promTotal.With(prometheus.Labels{"terminal": "xterm"}).Inc()

}

func main() {

    promlogConfig := &promlog.Config{}
    logger := promlog.New(promlogConfig)

    loger := log.NewLogfmtLogger(log.StdlibWriter{})
    loger.Log("legacy", true, "msg", "NewLogfmtLogger StdlibWriter")
    loger = log.NewLogfmtLogger(log.NewStdlibAdapter(logger))
    loger.Log("legacy", true, "msg", "NewLogfmtLogger NewStdlibAdapter")

    level.Info(logger).Log("msg", "Starting", "version", version.Info())
    level.Info(logger).Log("msg", "Build context", "context", version.BuildContext())

    ResponseWriteHeader := func(w http.ResponseWriter, status int) {
        if w == nil {
            return
        }
        //w.Header().Set("Content-Length", "2906")
        //w.Header().Set("Content-Type", "application/json; charset=utf-8")
        //w.Header().Set("X-Content-Type-Options", "nosniff")
        //w.WriteHeader(http.StatusOK)
        w.Header().Set("Content-Encoding", "gzip")
        w.Header().Set("Content-Type", "text/plain; version=0.0.4")
        w.WriteHeader(status)
    }
    ResponseWriteHeader(nil, 200)

    http.HandleFunc("/write", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("URL:", r.URL)
        fmt.Println("lastPush:", float64(time.Now().UnixNano())/1e9)
        fmt.Println("Content-Encoding:", r.Header.Get("Content-Encoding"))
        fmt.Println("Content-Type:", r.Header.Get("Content-Encoding"))
    })
    http.HandleFunc("/api/v2/write", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("URL:", r.URL)
        fmt.Println("lastPush:", float64(time.Now().UnixNano())/1e9)
        fmt.Println("Content-Encoding:", r.Header.Get("Content-Encoding"))
        fmt.Println("Content-Type:", r.Header.Get("Content-Type"))
    })

    http.HandleFunc("/query", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("URL:", r.URL)
        fmt.Fprintf(w, `{"results": []}`)
        w.WriteHeader(http.StatusOK)
    })
    http.HandleFunc("/api/v2/query", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("URL:", r.URL)
        fmt.Fprintf(w, ``)
        w.WriteHeader(http.StatusOK)
    })

    http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("URL:", r.URL)
        http.Error(w, "", http.StatusNoContent)
    })

    metricsPath := "/metrics"
    //http.Handle("/metrics", promhttp.Handler())
    //http.Handle("/metrics/exporter", promhttp.Handler())

    http.Handle("/metrics", promhttp.HandlerFor(promRegistry, promhttp.HandlerOpts{}))
    http.Handle("/metrics/exporter", promhttp.Handler())

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(`
<html>
    <head><title>Terminal Exporter Homepage</title></head>
    <body>
        <h1>Terminal Exporter</h1>
        <p><a href="` + metricsPath + `">Metrics</a></p>
        <p><a href="` + "/metrics/exporter" + `">Exporter Metrics</a></p>
    </body>
</html>`))
    })

    fmt.Println("terminal", "ListenAndServe", "url:", "http://localhost:9105")
    if err := http.ListenAndServe(":9105", nil); err != nil {
        fmt.Println("Error occur when start server:", err)
    }
}


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
搜索
«   2024年9月   »
1
2345678
9101112131415
16171819202122
23242526272829
30
网站分类
最新留言
文章归档
网站收藏
友情链接
图标汇集
Powered by Z-BlogPHP

  • Copyright ©2021 @liuzong All rights reserved.
  • 陕ICP备17016542号