Prometheus开发Exporter简介

Exporter 本身是一个http 服务,其指标结果只要符合 Prometheus 规范就可以被 Prometheus 使用。

Prometheus之Exporter开发-LMLPHP

Prometheus中metric的类型

Prometheus的Client Library提供度量的四种基本类型包括

// Counter 计数器
// Gauge  仪表盘
// Histogram 直方图
// Summary 概要

// Prometheus中metric的格式
// 格式:<metric name>{<label name>=<label value>, ...}
// 例如:api_http_requests_total{method="POST", handler="/messages"}

// metric name:  唯一标识,命名遵循[a-zA-Z_:][a-zA-Z0-9_:]*.
Counter
Gauge
Histogram

Histogram包含三个指标

<basename>:  度量值名称
<basename>_count:  样本反正总次数
<basename>_sum:  样本发生次数中值的总和
<basename>_bucket{le="+Inf"}: 每个区间的样本数
Summary
Histogram和Summary的对比

Prometheus中的Jobs和INSTANCES

Instances
// 仅采集的API endpoint
Jobs
// 相同目的的Instances
// 例如: 四个节点上的api-server
job: api-server
instance 1: 1.2.3.4:5670
instance 2: 1.2.3.4:5671
instance 3: 5.6.7.8:5670
instance 4: 5.6.7.8:5671
// Job: 会增加Job名称
// instance: 增加host: port

开发一个简单Exporter

监听HTTP请求返回一行字符串

lexporter_request_count{user="admin"} 1000

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)
}

Prometheus之Exporter开发-LMLPHP

配置Prometheus,将exporter到Prometheus中

Prometheus之Exporter开发-LMLPHP

Prometheus之Exporter开发-LMLPHP

计数器

example1

package main

import (
	"fmt"
	"net/http"
)

type Counter struct {
	count int64
}

func (c *Counter) Add(count int64) int64  {
	c.count += count
	return c.count
}


var counter = new(Counter)

func HelloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "lexporter_request_count{user=\"admin\"} %d",counter.Add(10) )
}

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

example2

package main

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

func main() {

	// counter
	requestTotal := prometheus.NewCounter(prometheus.CounterOpts{
		Name: "request_total",
		Help: "request total",
	})

	codeStatus := prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "status_code_total",
		Help: "status_code total",
	},[]string{"code"})

	requestTotal.Add(10)
	codeStatus.WithLabelValues("200").Add(10)
	codeStatus.WithLabelValues("500").Add(20)
	codeStatus.WithLabelValues("404").Add(30)

	prometheus.MustRegister(requestTotal)
	prometheus.MustRegister(codeStatus)

	// 暴露
	http.Handle("/metrics", promhttp.Handler())
	http.ListenAndServe(":8888", nil)
}

Prometheus之Exporter开发-LMLPHP

Gauge(固定label和非固定label)
package main

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

func main()  {
	// counter
	// guage
	// historgram
	// summary

	// metrics name(label=label_value) metrics_valu
	// 有lable
	// label/label_value  固定

	// 无label(固定lable)
	// lable/label_value  变化的
	cpu := prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "cpu",
		Help: "cpu total",

		// 没有lable和固定lable一样的
		ConstLabels: prometheus.Labels{"a":"xxx"},
	})


	// 非固定label
	disk := prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "disk",
		Help: "disk total",

	},[]string{"mount"})

	cpu.Set(2222)
	disk.WithLabelValues("/mnt/sda1:").Set(100)
	disk.WithLabelValues("/mnt/sda2:").Set(200)
	disk.WithLabelValues("/mnt/sda3:").Set(200)
	disk.WithLabelValues("/mnt/sda4:").Set(200)

	// 注册指标信息
	prometheus.MustRegister(cpu)
	prometheus.MustRegister(disk)

	// 暴露
	http.Handle("/metrics",promhttp.Handler())
	http.ListenAndServe(":8888",nil)

}
historgram

example1

package main

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

func main() {

	// historgram
	request_time := prometheus.NewHistogramVec(prometheus.HistogramOpts{
		Name: "request_time",
		Help: "request time",
	},[]string{"url"})



	prometheus.MustRegister(request_time)
	request_time.WithLabelValues("/aaa").Observe(6)


	// 暴露
	http.Handle("/metrics", promhttp.Handler())
	http.ListenAndServe(":8888", nil)
}

summary
package main

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

func main() {

	// summary
	requestsummary := prometheus.NewSummaryVec(prometheus.SummaryOpts{
		Name: "request_time_summary",
		Help: "request time summary",
		Objectives: map[float64]float64{0.5: 0.05,0.9:0.09},
	},[]string{"url"})



	prometheus.MustRegister(requestsummary)


	requestsummary.WithLabelValues("/aaa").Observe(6)
	requestsummary.WithLabelValues("/aaa").Observe(2)

	// 暴露
	http.Handle("/metrics", promhttp.Handler())
	http.ListenAndServe(":8888", nil)
}

值的修改(事件触发或者时间触发)
package main

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

func main()  {
	// 无label(固定lable)
	// lable/label_value  变化的
	cpu := prometheus.NewGauge(prometheus.GaugeOpts{
		Name: "cpu",
		Help: "cpu total",

		// 没有lable和固定lable一样的
		ConstLabels: prometheus.Labels{"a":"xxx"},
	})


	// 非固定label
	disk := prometheus.NewGaugeVec(prometheus.GaugeOpts{
		Name: "disk",
		Help: "disk total",

	},[]string{"mount"})

	cpu.Set(2222)
	disk.WithLabelValues("/mnt/sda1:").Set(100)
	disk.WithLabelValues("/mnt/sda2:").Set(200)
	disk.WithLabelValues("/mnt/sda3:").Set(200)
	disk.WithLabelValues("/mnt/sda4:").Set(200)


	codeStatus := prometheus.NewCounterVec(prometheus.CounterOpts{
		Name: "status_code_total",
		Help: "status_code total",
	},[]string{"code"})


	codeStatus.WithLabelValues("200").Add(10)
	codeStatus.WithLabelValues("500").Add(20)
	codeStatus.WithLabelValues("404").Add(30)
	// counter
	requestTotal := prometheus.NewCounter(prometheus.CounterOpts{
		Name: "request_total",
		Help: "request total",
	})

	requestTotal.Add(10)

	// 值的修改
	// 修改的时间 => 触发
	// 时间触发
	// 磁盘使用, cpu使用,内存使用
	go func() {
		for range time.Tick(time.Second) {
			disk.WithLabelValues("/mnt/sda1").Set(float64(rand.Int()))
		}
	}()

	// 事件触发,业务请求
	http.HandleFunc("/",func(w http.ResponseWriter,r *http.Request){
		requestTotal.Inc()
		codeStatus.WithLabelValues(strconv.Itoa(rand.Intn(5) * 100)).Add(1)
		fmt.Fprintf(w,"hi")
	})



	// 注册指标信息
	prometheus.MustRegister(cpu)
	prometheus.MustRegister(disk)
	prometheus.MustRegister(requestTotal)

	// 暴露
	http.Handle("/metrics",promhttp.Handler())
	http.ListenAndServe(":8888",nil)
}

09-20 08:04