1. 先自定义exporter
package utils import ( "github.com/gin-gonic/gin" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/log" ) // 最终生成的指标数据 // # HELP dns_query_count_total Count of DNS Query. // # TYPE dns_query_count_total counter // dns_query_count_total{kkkk="self",net="udp",query_proto="dns","query_help": "queryHelp", "xxxxxx": "queryHelp"} 999999 // 1. 定义一个结构体,用于存放描述信息 type Exporter struct { queryCountDesc *prometheus.Desc } // 2. 定义一个Collector接口,用于存放两个必备函数,Describe和Collect type Collector interface { Describe(chan<- *prometheus.Desc) Collect(chan<- prometheus.Metric) } // 3. 定义两个必备函数Describe和Collect func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { // 将描述信息放入队列 ch <- e.queryCountDesc } func (e *Exporter) Collect(ch chan<- prometheus.Metric) { // 采集业务指标数据 queryCount := e.QueryState() // 获取指标数据值 ch <- prometheus.MustNewConstMetric( e.queryCountDesc, // 将指标数据与自定义描述信息绑定 prometheus.CounterValue, // 指定该指标数据的类型,这里表示counter类型 float64(queryCount), // 指标数据的值转为float64类型,必须的 "dns", // 指标的标签值,多个标签值的话,继续往后写即可。与NewExporter中prometheus.NewDesc的第三个参数 "udp", // 是一一对应的。这里的dns就是query_proto的值 "self", ) } // 4. 自定义一个生成业务指标数据的函数 func (e *Exporter) QueryState() (queryCount float64) { queryCount = 999999 return } // 5. 定义一个实例化函数,用于生成prometheus数据 func NewExporter() *Exporter { return &Exporter{ queryCountDesc: prometheus.NewDesc( "dns_query_count_total", // 自定义指标名称 "Count of DNS Query.", // 指标的help信息 []string{"query_proto", "net", "kkkk"}, // 指标的标签名称,多个就写到数组里,与Collect中prometheus.MustNewConstMetric最后的几个标签值是一一对应的 prometheus.Labels{"query_help": "queryHelp", "xxxxxx": "queryHelp"}, // 也是定义指标标签名称,不过通常用于定义全局唯一的指标标签名称,用的少一些。 // 这个不是必须的, 不需要的话,可以写为nil。 ), } } func getGatherers() (reg *prometheus.Registry, gatherers *prometheus.Gatherers) { // 6. 实例化并注册数据采集器exporter exporter := NewExporter() registry := prometheus.NewPedanticRegistry() registry.MustRegister(exporter) // 7. 定义一个采集数据的采集器集合,它可以合并多个不同的采集器数据到一个结果集合中 gatherers = &prometheus.Gatherers{ // prometheus.DefaultGatherer, // 默认的数据采集器,包含go运行时的指标信息 registry, // 自定义的采集器 } return registry, gatherers } // 8. 启动http服务 // 8.1 (与gin框架集成) func PrometheusHandler() gin.HandlerFunc { registry, gatherers := getGatherers() h := promhttp.InstrumentMetricHandler( registry, promhttp.HandlerFor(gatherers, promhttp.HandlerOpts{ ErrorLog: log.NewErrorLogger(), // 采集过程中如果出现错误,记录日志 ErrorHandling: promhttp.ContinueOnError, // 采集过程中如果出现错误,继续采集其他数据,不会中断采集器的工作 }), ) return func(c *gin.Context) { h.ServeHTTP(c.Writer, c.Request) } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 8.2 (独立启动,不与gin框架集成) // func init() { // _, gatherers := getGatherers() // h := promhttp.HandlerFor(gatherers, // // HandlerFor函数传递上边的gatherers对象,并返回一个httpHandler对象h。 // // 这个httpHandler对象h可以调用其自身的ServHTTP函数来接收HTTP请求,并返回响应 // promhttp.HandlerOpts{ // ErrorLog: log.NewErrorLogger(), // 采集过程中如果出现错误,记录日志 // ErrorHandling: promhttp.ContinueOnError, // 采集过程中如果出现错误,继续采集其他数据,不会中断采集器的工作 // }) // http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) { // fmt.Println("listen exporter on :9999") // h.ServeHTTP(w, r) // }) // log.Fatal(http.ListenAndServe(":9999", nil)) // } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2. gin框架路由配置
package routes import ( "dnsmanager/utils" "github.com/gin-gonic/gin" ) func SetRoutes(router *gin.Engine) { router.Use(gin.Recovery()) // error handle router.GET("/metrics", utils.PrometheusHandler()) ------------------> 设置路由 }