Golang实现自定义Prometheus导出器

Golang实现自定义Prometheus导出器 我正在尝试创建一个自定义的Prometheus导出器。虽然已经成功将指标发送到我的端口,但如何在使用新值更新指标时"覆盖"之前的指标值?我通过API GET请求获取一个数字,并将该数字传递给指标。这个数字可能在一分钟后发生变化,我该如何更新该指标?我四处查阅后得到的答案是在Update()方法中使用MustNewConstMetric,但我完全不知道具体该如何操作。有人能帮忙解释一下吗?以下是我目前的代码:

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/tidwall/gjson"
)

var productionTotal = prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "production_total", Help: ""})

func init() {
	prometheus.MustRegister(productionTotal)
	productionTotal.Set(getTotal("production"))
}

func getTotal(x string) float64 {
	URL := fmt.Sprintf("apigetrequest")
	res, err := http.Get(URL)
	if err != nil {
		panic(err.Error())
	}
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		panic(err.Error())
	}
	bodyString := string(body)
	value := gjson.Get(bodyString, "result.total_count")
	return float64(value.Num)
}

更多关于Golang实现自定义Prometheus导出器的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang实现自定义Prometheus导出器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在自定义Prometheus导出器中更新指标值,您需要使用Set()方法来覆盖之前的指标值。您的代码已经接近正确,但需要添加定期更新机制。以下是修改后的代码示例:

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/tidwall/gjson"
)

var productionTotal = prometheus.NewGauge(prometheus.GaugeOpts{
	Name: "production_total", 
	Help: "Total production count",
})

func init() {
	prometheus.MustRegister(productionTotal)
	
	// 启动定期更新指标的后台goroutine
	go updateMetricsPeriodically()
}

func updateMetricsPeriodically() {
	ticker := time.NewTicker(1 * time.Minute) // 每分钟更新一次
	defer ticker.Stop()
	
	for {
		select {
		case <-ticker.C:
			updateProductionTotal()
		}
	}
}

func updateProductionTotal() {
	newValue := getTotal("production")
	productionTotal.Set(newValue) // 这会覆盖之前的指标值
	fmt.Printf("Updated production_total to: %f\n", newValue)
}

func getTotal(x string) float64 {
	URL := fmt.Sprintf("apigetrequest")
	res, err := http.Get(URL)
	if err != nil {
		fmt.Printf("Error fetching data: %v\n", err)
		return 0
	}
	defer res.Body.Close()
	
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Printf("Error reading response: %v\n", err)
		return 0
	}
	
	bodyString := string(body)
	value := gjson.Get(bodyString, "result.total_count")
	return float64(value.Num)
}

func main() {
	// 设置HTTP处理程序用于Prometheus抓取
	http.Handle("/metrics", promhttp.Handler())
	
	// 初始更新一次指标
	updateProductionTotal()
	
	fmt.Println("Starting server on :8080")
	http.ListenAndServe(":8080", nil)
}

关于MustNewConstMetric的使用,这通常用于自定义收集器(Collector)模式。如果您想使用这种方式,这里是一个示例:

type customCollector struct {
	productionTotal *prometheus.Desc
}

func newCustomCollector() *customCollector {
	return &customCollector{
		productionTotal: prometheus.NewDesc(
			"production_total",
			"Total production count",
			nil, nil,
		),
	}
}

func (c *customCollector) Describe(ch chan<- *prometheus.Desc) {
	ch <- c.productionTotal
}

func (c *customCollector) Collect(ch chan<- prometheus.Metric) {
	currentValue := getTotal("production")
	ch <- prometheus.MustNewConstMetric(
		c.productionTotal,
		prometheus.GaugeValue,
		currentValue,
	)
}

// 在主函数中注册自定义收集器
func main() {
	collector := newCustomCollector()
	prometheus.MustRegister(collector)
	
	http.Handle("/metrics", promhttp.Handler())
	fmt.Println("Starting server on :8080")
	http.ListenAndServe(":8080", nil)
}

第一种方法使用Gauge的Set()方法更简单直接,适合您的用例。每次调用Set()都会覆盖之前的指标值,Prometheus在抓取时会获取到最新的数值。

回到顶部