package msgbus import ( "fmt" "net/http" sync "github.com/sasha-s/go-deadlock" log "github.com/sirupsen/logrus" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) // DefObjectives ... var DefObjectives = map[float64]float64{ 0.50: 0.05, 0.90: 0.01, 0.95: 0.005, 0.99: 0.001, } // Metrics ... type Metrics struct { sync.RWMutex namespace string metrics map[string]prometheus.Metric countervecs map[string]*prometheus.CounterVec guagevecs map[string]*prometheus.GaugeVec sumvecs map[string]*prometheus.SummaryVec } // NewMetrics ... func NewMetrics(namespace string) *Metrics { return &Metrics{ namespace: namespace, metrics: make(map[string]prometheus.Metric), countervecs: make(map[string]*prometheus.CounterVec), guagevecs: make(map[string]*prometheus.GaugeVec), sumvecs: make(map[string]*prometheus.SummaryVec), } } // NewCounter ... func (m *Metrics) NewCounter(subsystem, name, help string) prometheus.Counter { counter := prometheus.NewCounter( prometheus.CounterOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, }, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.metrics[key] = counter m.Unlock() prometheus.MustRegister(counter) return counter } // NewCounterFunc ... func (m *Metrics) NewCounterFunc(subsystem, name, help string, f func() float64) prometheus.CounterFunc { counter := prometheus.NewCounterFunc( prometheus.CounterOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, }, f, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.metrics[key] = counter m.Unlock() prometheus.MustRegister(counter) return counter } // NewCounterVec ... func (m *Metrics) NewCounterVec(subsystem, name, help string, labels []string) *prometheus.CounterVec { countervec := prometheus.NewCounterVec( prometheus.CounterOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, }, labels, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.countervecs[key] = countervec m.Unlock() prometheus.MustRegister(countervec) return countervec } // NewGauge ... func (m *Metrics) NewGauge(subsystem, name, help string) prometheus.Gauge { guage := prometheus.NewGauge( prometheus.GaugeOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, }, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.metrics[key] = guage m.Unlock() prometheus.MustRegister(guage) return guage } // NewGaugeFunc ... func (m *Metrics) NewGaugeFunc(subsystem, name, help string, f func() float64) prometheus.GaugeFunc { guage := prometheus.NewGaugeFunc( prometheus.GaugeOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, }, f, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.metrics[key] = guage m.Unlock() prometheus.MustRegister(guage) return guage } // NewGaugeVec ... func (m *Metrics) NewGaugeVec(subsystem, name, help string, labels []string) *prometheus.GaugeVec { guagevec := prometheus.NewGaugeVec( prometheus.GaugeOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, }, labels, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.guagevecs[key] = guagevec m.Unlock() prometheus.MustRegister(guagevec) return guagevec } // NewSummary ... func (m *Metrics) NewSummary(subsystem, name, help string) prometheus.Summary { summary := prometheus.NewSummary( prometheus.SummaryOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, Objectives: DefObjectives, }, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.metrics[key] = summary m.Unlock() prometheus.MustRegister(summary) return summary } // NewSummaryVec ... func (m *Metrics) NewSummaryVec(subsystem, name, help string, labels []string) *prometheus.SummaryVec { sumvec := prometheus.NewSummaryVec( prometheus.SummaryOpts{ Namespace: m.namespace, Subsystem: subsystem, Name: name, Help: help, Objectives: DefObjectives, }, labels, ) key := fmt.Sprintf("%s_%s", subsystem, name) m.Lock() m.sumvecs[key] = sumvec m.Unlock() prometheus.MustRegister(sumvec) return sumvec } // Counter ... func (m *Metrics) Counter(subsystem, name string) prometheus.Counter { key := fmt.Sprintf("%s_%s", subsystem, name) return m.metrics[key].(prometheus.Counter) } // CounterVec ... func (m *Metrics) CounterVec(subsystem, name string) *prometheus.CounterVec { key := fmt.Sprintf("%s_%s", subsystem, name) m.RLock() defer m.RUnlock() return m.countervecs[key] } // Gauge ... func (m *Metrics) Gauge(subsystem, name string) prometheus.Gauge { key := fmt.Sprintf("%s_%s", subsystem, name) m.RLock() defer m.RUnlock() return m.metrics[key].(prometheus.Gauge) } // GaugeVec ... func (m *Metrics) GaugeVec(subsystem, name string) *prometheus.GaugeVec { key := fmt.Sprintf("%s_%s", subsystem, name) m.RLock() defer m.RUnlock() return m.guagevecs[key] } // Summary ... func (m *Metrics) Summary(subsystem, name string) prometheus.Summary { key := fmt.Sprintf("%s_%s", subsystem, name) m.RLock() defer m.RUnlock() return m.metrics[key].(prometheus.Summary) } // SummaryVec ... func (m *Metrics) SummaryVec(subsystem, name string) *prometheus.SummaryVec { key := fmt.Sprintf("%s_%s", subsystem, name) m.RLock() defer m.RUnlock() return m.sumvecs[key] } // Handler ... func (m *Metrics) Handler() http.Handler { return promhttp.Handler() } // Run ... func (m *Metrics) Run(addr string) { http.Handle("/", m.Handler()) log.Infof("metrics endpoint listening on %s", addr) log.Fatal(http.ListenAndServe(addr, nil)) }