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)) e.gauge.Collect(ch) e.gaugeVec.Collect(ch) }
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 `) metricsPath := "/metrics" listenAddress := "0.0.0.0:18081" metricsPrefix := "fake" exporter := NewExporter(metricsPrefix) prometheus.MustRegister(exporter) prometheus.MustRegister(version) http.Handle(metricsPath, prometheus.Handler()) http.Handle("/", prometheus.Handler()) fmt.Println(http.ListenAndServe(listenAddress, nil)) }
|
这是个最简单的例子,Prometheus官网推荐我们参考haproxy_exporter实现,大家可参考这里
Node_exporter算是比较复杂的实现,有兴趣也可以看看.
参考文章: