161 lines
4.3 KiB
Go
161 lines
4.3 KiB
Go
package metric
|
|
|
|
import (
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"sync"
|
|
)
|
|
|
|
const missVal = "MissLabel"
|
|
|
|
// CounterVecDecorator Add safe decorator
|
|
type CounterVecDecorator struct {
|
|
*prometheus.CounterVec
|
|
secureLabels []string
|
|
once *sync.Once
|
|
}
|
|
|
|
func NewCounterVec(opts prometheus.CounterOpts, labelNames []string) *CounterVecDecorator {
|
|
v := &CounterVecDecorator{prometheus.NewCounterVec(opts, labelNames), labelNames, &sync.Once{}}
|
|
|
|
return v
|
|
}
|
|
|
|
// With is secure wrap for with of prometheus.CounterVec
|
|
// there is no panic, and always calculate to metrics , if miss values, will calculate to MissLabel
|
|
// It's secure
|
|
func (v *CounterVecDecorator) With(labels prometheus.Labels) prometheus.Counter {
|
|
// To avoid initialization sequence, so must delay register to with func
|
|
v.once.Do(func() {
|
|
Register(v)
|
|
})
|
|
|
|
safeLabels := labelAlignment(v.secureLabels, labels)
|
|
|
|
//
|
|
c, err := v.GetMetricWith(safeLabels)
|
|
|
|
if err != nil {
|
|
// should never happen , but should still add handler to record alert
|
|
// TODO singleton alert Gauge and return an alert counter
|
|
|
|
}
|
|
return c
|
|
}
|
|
|
|
// GaugeVecDecorator Add safe decorator
|
|
type GaugeVecDecorator struct {
|
|
*prometheus.GaugeVec
|
|
secureLabels []string
|
|
once *sync.Once
|
|
}
|
|
|
|
func NewGaugeVec(opts prometheus.GaugeOpts, labelNames []string) *GaugeVecDecorator {
|
|
v := &GaugeVecDecorator{prometheus.NewGaugeVec(opts, labelNames), labelNames, &sync.Once{}}
|
|
|
|
return v
|
|
}
|
|
|
|
// With is secure wrap for with of prometheus.GaugeVec
|
|
// there is no panic, and always calculate to metrics , if miss values, will calculate to MissLabel
|
|
// It's secure
|
|
func (v *GaugeVecDecorator) With(labels prometheus.Labels) prometheus.Gauge {
|
|
// To avoid initialization sequence, so must delay register to with func
|
|
v.once.Do(func() {
|
|
Register(v)
|
|
})
|
|
|
|
safeLabels := labelAlignment(v.secureLabels, labels)
|
|
//
|
|
c, err := v.GetMetricWith(safeLabels)
|
|
|
|
if err != nil {
|
|
// should never happen , but should still add handler to record alert
|
|
// TODO singleton alert Gauge and return
|
|
}
|
|
return c
|
|
}
|
|
|
|
// HistogramVecDecorator Add safe
|
|
type HistogramVecDecorator struct {
|
|
*prometheus.HistogramVec
|
|
secureLabels []string
|
|
once *sync.Once
|
|
}
|
|
|
|
func NewHistogramVec(opts prometheus.HistogramOpts, labelNames []string) *HistogramVecDecorator {
|
|
v := &HistogramVecDecorator{prometheus.NewHistogramVec(opts, labelNames), labelNames, &sync.Once{}}
|
|
|
|
return v
|
|
}
|
|
|
|
// With is secure wrap for with of prometheus.HistogramVec
|
|
// there is no panic, and always calculate to metrics , if miss values, will calculate to MissLabel
|
|
// It's secure
|
|
func (v *HistogramVecDecorator) With(labels prometheus.Labels) prometheus.Observer {
|
|
// To avoid initialization sequence, so must delay register to with func
|
|
v.once.Do(func() {
|
|
Register(v)
|
|
})
|
|
|
|
safeLabels := labelAlignment(v.secureLabels, labels)
|
|
//
|
|
c, err := v.GetMetricWith(safeLabels)
|
|
|
|
if err != nil {
|
|
// should never happen , but should still add handler to record alert
|
|
// TODO singleton alert Histogram and return
|
|
}
|
|
return c
|
|
}
|
|
|
|
// SummaryVecDecorator Add safe
|
|
type SummaryVecDecorator struct {
|
|
*prometheus.SummaryVec
|
|
secureLabels []string
|
|
once *sync.Once
|
|
}
|
|
|
|
func NewSummaryVec(opts prometheus.SummaryOpts, labelNames []string) *SummaryVecDecorator {
|
|
v := &SummaryVecDecorator{prometheus.NewSummaryVec(opts, labelNames), labelNames, &sync.Once{}}
|
|
//if len(autoReg) == 0 || autoReg[0] == true {
|
|
// Register(v)
|
|
//}
|
|
return v
|
|
}
|
|
|
|
// With is secure wrap for with of prometheus.SummaryVec
|
|
// there is no panic, and always calculate to metrics , if miss values, will calculate to MissLabel
|
|
// It's secure
|
|
func (v *SummaryVecDecorator) With(labels prometheus.Labels) prometheus.Observer {
|
|
// To avoid initialization sequence, so must delay register to with func
|
|
v.once.Do(func() {
|
|
Register(v)
|
|
})
|
|
|
|
safeLabels := labelAlignment(v.secureLabels, labels)
|
|
//
|
|
c, err := v.GetMetricWith(safeLabels)
|
|
|
|
if err != nil {
|
|
// should never happen , but should still add handler to record alert
|
|
// TODO singleton alert Gauge and return
|
|
}
|
|
//prometheus.NewCounter(v.SummaryVec.)
|
|
return c
|
|
}
|
|
|
|
// 标签对齐
|
|
func labelAlignment(labelNames []string, labels prometheus.Labels) prometheus.Labels {
|
|
|
|
newLabels := make(prometheus.Labels, len(labelNames))
|
|
|
|
for _, val := range labelNames {
|
|
if v, ok := labels[val]; ok {
|
|
newLabels[val] = v
|
|
} else {
|
|
newLabels[val] = missVal
|
|
}
|
|
}
|
|
return newLabels
|
|
}
|