uniugm/admin/lib/prom/promethus.go

212 lines
6.9 KiB
Go
Raw Normal View History

2025-04-18 17:17:23 +08:00
package prom
import (
"fmt"
"sync/atomic"
ginPprof "github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func NewCounter(name string) *PromeCounterStatMgr {
mgr := new(PromeCounterStatMgr)
mgr.promeStatMgr = newPromeStatMgr(name, func(defaultLabels, labels []string) prometheus.Collector {
return newCounterVec(name, defaultLabels, labels)
})
return mgr
}
func NewGauge(name string) *PromeGaugeStatMgr {
mgr := new(PromeGaugeStatMgr)
mgr.promeStatMgr = newPromeStatMgr(name, func(defaultLabels, labels []string) prometheus.Collector {
return newGagueVec(name, defaultLabels, labels)
})
return mgr
}
func NewHistogram(name string, buckets []float64) *PromeHistogramStatMgr {
mgr := new(PromeHistogramStatMgr)
mgr.promeStatMgr = newPromeStatMgr(name, func(defaultLabels, labels []string) prometheus.Collector {
return newHistogramVec(name, defaultLabels, labels, buckets)
})
return mgr
}
type PromeCounterStatMgr struct {
*promeStatMgr
}
// InitLabels 初始化指标的标签说明,以后每次收集指标都给上标签值
func (c *PromeCounterStatMgr) InitLabels(labels []string) *PromeCounterStatMgr {
return c.InitDefaultLabels(nil, labels)
}
// InitDefaultLabels 带上默认标签例如某些服务启动就能知道标签值比如app_nameapp_id等
// 又不想每次收集指标都传递标签值,可以用此方法一开始就设置好
func (c *PromeCounterStatMgr) InitDefaultLabels(defaultLabels map[string]string, labels []string) *PromeCounterStatMgr {
c.promeStatMgr.withDefaultLabels(defaultLabels, labels)
return c
}
// LabelValues 准备收集指标,调用这个传递标签值,后续再给上指标值
// 即c.LabelValues("xxx").Add(234)
func (c *PromeCounterStatMgr) LabelValues(labels ...string) prometheus.Counter {
return c.promeStatMgr.getCounterWithLabels(labels...)
}
type PromeGaugeStatMgr struct {
*promeStatMgr
}
// InitLabels 初始化指标的标签说明,以后每次收集指标都给上标签值
func (c *PromeGaugeStatMgr) InitLabels(labels []string) *PromeGaugeStatMgr {
return c.InitDefaultLabels(nil, labels)
}
// InitDefaultLabels 带上默认标签例如某些服务启动就能知道标签值比如app_nameapp_id等
// 又不想每次收集指标都传递标签值,可以用此方法一开始就设置好
func (c *PromeGaugeStatMgr) InitDefaultLabels(defaultLabels map[string]string, labels []string) *PromeGaugeStatMgr {
c.promeStatMgr.withDefaultLabels(defaultLabels, labels)
return c
}
// LabelValues 准备收集指标,调用这个传递标签值,后续再给上指标值
// 即c.LabelValues("xxx").Add(234)
func (c *PromeGaugeStatMgr) LabelValues(labels ...string) prometheus.Gauge {
return c.promeStatMgr.getGaugeWithLabels(labels...)
}
type PromeHistogramStatMgr struct {
*promeStatMgr
}
// InitLabels 初始化指标的标签说明,以后每次收集指标都给上标签值
func (c *PromeHistogramStatMgr) InitLabels(labels []string) *PromeHistogramStatMgr {
return c.InitDefaultLabels(nil, labels)
}
// InitDefaultLabels 带上默认标签例如某些服务启动就能知道标签值比如app_nameapp_id等
// 又不想每次收集指标都传递标签值,可以用此方法一开始就设置好
func (c *PromeHistogramStatMgr) InitDefaultLabels(defaultLabels map[string]string, labels []string) *PromeHistogramStatMgr {
c.promeStatMgr.withDefaultLabels(defaultLabels, labels)
return c
}
// LabelValues 准备收集指标,调用这个传递标签值,后续再给上指标值
// 即c.LabelValues("xxx").Add(234)
func (c *PromeHistogramStatMgr) LabelValues(labels ...string) prometheus.Observer {
return c.promeStatMgr.getHistogramWithLabels(labels...)
}
type promeStatMgr struct {
collector prometheus.Collector
name string
newCollectorFun func(defaultLabels, labels []string) prometheus.Collector
defaultLabelsValue []string
initCounter int32
}
func (mgr *promeStatMgr) withDefaultLabels(defaultLabels map[string]string, labels []string) {
if atomic.AddInt32(&mgr.initCounter, 1) > 1 {
panic(fmt.Errorf("promethus vec labels must init once"))
}
defaultLabelKeys := make([]string, 0)
defaultLabelValues := make([]string, 0)
for k, v := range defaultLabels {
defaultLabelKeys = append(defaultLabelKeys, k)
defaultLabelValues = append(defaultLabelValues, v)
}
mgr.defaultLabelsValue = defaultLabelValues
mgr.collector = mgr.newCollectorFun(defaultLabelKeys, labels)
return
}
func (mgr *promeStatMgr) joinLabels(labels ...string) []string {
newLabels := make([]string, 0, len(mgr.defaultLabelsValue)+len(labels))
newLabels = append(newLabels, mgr.defaultLabelsValue...)
newLabels = append(newLabels, labels...)
return newLabels
}
func (mgr *promeStatMgr) getCounterWithLabels(labels ...string) prometheus.Counter {
newLabels := mgr.joinLabels(labels...)
return mgr.collector.(*prometheus.CounterVec).WithLabelValues(newLabels...)
}
func (mgr *promeStatMgr) getGaugeWithLabels(labels ...string) prometheus.Gauge {
newLabels := mgr.joinLabels(labels...)
return mgr.collector.(*prometheus.GaugeVec).WithLabelValues(newLabels...)
}
func (mgr *promeStatMgr) getHistogramWithLabels(labels ...string) prometheus.Observer {
newLabels := mgr.joinLabels(labels...)
return mgr.collector.(*prometheus.HistogramVec).WithLabelValues(newLabels...)
}
func newPromeStatMgr(name string,
newCollectorFun func(defaultLabelsKey []string, labels []string) prometheus.Collector) *promeStatMgr {
mgr := new(promeStatMgr)
mgr.name = name
mgr.newCollectorFun = newCollectorFun
return mgr
}
func newCounterVec(name string, defaultLabels []string, dynamicLabels []string) prometheus.Collector {
vec := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: name,
Help: name,
},
append(defaultLabels, dynamicLabels...),
)
prometheus.MustRegister(vec)
return vec
}
func newGagueVec(name string, defaultLabels []string, dynamicLabels []string) prometheus.Collector {
vec := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: name,
Help: name,
},
append(defaultLabels, dynamicLabels...),
)
prometheus.MustRegister(vec)
return vec
}
func newHistogramVec(name string, defaultLabels []string, dynamicLabels []string, buckets []float64) prometheus.Collector {
vec := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: name,
Help: name,
Buckets: buckets,
},
append(defaultLabels, dynamicLabels...),
)
prometheus.MustRegister(vec)
return vec
}
func NewEngine(enablePprof bool) *gin.Engine {
//gin.SetMode(gin.ReleaseMode)
engine := gin.New()
engine.Use(gin.Recovery())
RouteEngine(engine, enablePprof)
return engine
}
func RouteEngine(engine *gin.Engine, enablePprof bool) {
if enablePprof {
ginPprof.Register(engine)
}
engine.Use(gin.LoggerWithConfig(gin.LoggerConfig{
SkipPaths: []string{"/metrics"},
}))
engine.GET("/metrics", gin.WrapH(promhttp.Handler()))
}