Z.S.K.'s Records

Prometheus学习(编写业务Exporter)

Prometheus官网维护了大量的Exporter, 很多都是开箱即用,非常方便,但有时业务要接入Prometheus时, 还需要业务端开发Exporter,好在Prometheus定制了一套流程的Client开发流程,非常容易接入.

实现方式

编写 Exporter 的两种方式,分别是:

  • 自己的代码定时刷新值
  • 在 Prometheus 抓取的时候实时获取值

这两种方式本质上没有差别,但是在采集时有一些差别:

  • 方式一可以以几乎忽略的延迟返回监控数据, 但无法保证数据是最新值.
  • 方式二可能会因为一些难以获取的值而超时或者很久才会返回值

一般情况下都是使用第二种方式,只需要我们在业务代码中实现Collect接口即可

Prometheus的官网写明了实现自己的exporter需要的流程, 看writing_exporters

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package main

import (
"fmt"
"time"
"github.com/prometheus/client_golang/prometheus"
"net/http"
"math/rand"
)

var (
//版本信息
version = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "fake_version",
Help: "Version information about this binary",
ConstLabels: map[string]string{
"version": "v1.0",
},
})
)

type Exporter struct {
gauge prometheus.Gauge
gaugeVec prometheus.GaugeVec
}

func NewExporter(metricsPrefix string) *Exporter {
gauge := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: metricsPrefix,
Name: "gauge_metric",
Help: "This is a gauge metric"})

gaugeVec := *prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: metricsPrefix,
Name: "gauge_vec_metric",
Help: "This is a gauga vece metric"},
[]string{"myLabel"})

return &Exporter{
gauge: gauge,
gaugeVec: gaugeVec,
}
}

func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
// --------
// 业务逻辑
timestamp := time.Now().Unix()
fmt.Println("Timestamp: ", timestamp)
rand.Seed(timestamp)
ranint := rand.Intn(10000)
fmt.Println("Random: ", ranint)
e.gauge.Set(float64(timestamp))
e.gaugeVec.WithLabelValues("helloworld").Set(float64(ranint))
// --------
// Called use a concurrency safe way
e.gauge.Collect(ch)
e.gaugeVec.Collect(ch)
}

// metric 描述, 可被重写
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
e.gauge.Describe(ch)
e.gaugeVec.Describe(ch)
}

func main() {
fmt.Println(`
prometheus exporter example,
metrics expose at http://:18081/metrics
`)

// Define parameters
metricsPath := "/metrics"
listenAddress := "0.0.0.0:18081"
metricsPrefix := "fake"

// Register exporter to Prometheus, call Collect
exporter := NewExporter(metricsPrefix)
prometheus.MustRegister(exporter)
prometheus.MustRegister(version)

// Launch http service
http.Handle(metricsPath, prometheus.Handler())
http.Handle("/", prometheus.Handler())
fmt.Println(http.ListenAndServe(listenAddress, nil))
}

这是个最简单的例子,Prometheus官网推荐我们参考haproxy_exporter实现,大家可参考这里

Node_exporter算是比较复杂的实现,有兴趣也可以看看.

参考文章:

转载请注明原作者: 周淑科(https://izsk.me)

 wechat
Scan Me To Read on Phone
I know you won't do this,but what if you did?