2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
24 "github.com/gorilla/mux"
25 "github.com/prometheus/client_golang/prometheus"
26 "github.com/prometheus/client_golang/prometheus/promauto"
27 "github.com/prometheus/client_golang/prometheus/promhttp"
31 //-----------------------------------------------------------------------------
33 //-----------------------------------------------------------------------------
34 type CounterOpts prometheus.Opts
35 type Counter prometheus.Counter
36 type Gauge prometheus.Gauge
38 type CounterVec struct {
39 Vec *prometheus.CounterVec
44 type GaugeVec struct {
45 Vec *prometheus.GaugeVec
50 func strSliceCompare(a, b []string) bool {
62 //-----------------------------------------------------------------------------
64 //-----------------------------------------------------------------------------
66 type MetricGroupsCache struct {
67 sync.RWMutex //This is for map locking
68 counters map[string]Counter
69 gauges map[string]Gauge
72 func (met *MetricGroupsCache) CIs(metric string) bool {
75 _, ok := met.counters[metric]
79 func (met *MetricGroupsCache) CGet(metric string) Counter {
82 return met.counters[metric]
85 func (met *MetricGroupsCache) CInc(metric string) {
88 met.counters[metric].Inc()
91 func (met *MetricGroupsCache) CAdd(metric string, val float64) {
94 met.counters[metric].Add(val)
97 func (met *MetricGroupsCache) GIs(metric string) bool {
100 _, ok := met.gauges[metric]
104 func (met *MetricGroupsCache) GGet(metric string) Gauge {
107 return met.gauges[metric]
110 func (met *MetricGroupsCache) GSet(metric string, val float64) {
113 met.gauges[metric].Set(val)
116 func (met *MetricGroupsCache) GAdd(metric string, val float64) {
119 met.gauges[metric].Add(val)
122 func (met *MetricGroupsCache) GInc(metric string) {
125 met.gauges[metric].Inc()
128 func (met *MetricGroupsCache) GDec(metric string) {
131 met.gauges[metric].Dec()
134 func (met *MetricGroupsCache) CombineCounterGroupsWithPrefix(prefix string, srcs ...map[string]Counter) {
137 for _, src := range srcs {
138 for k, v := range src {
139 met.counters[prefix+k] = v
144 func (met *MetricGroupsCache) CombineCounterGroups(srcs ...map[string]Counter) {
147 for _, src := range srcs {
148 for k, v := range src {
154 func (met *MetricGroupsCache) CombineGaugeGroupsWithPrefix(prefix string, srcs ...map[string]Gauge) {
157 for _, src := range srcs {
158 for k, v := range src {
159 met.gauges[prefix+k] = v
164 func (met *MetricGroupsCache) CombineGaugeGroups(srcs ...map[string]Gauge) {
167 for _, src := range srcs {
168 for k, v := range src {
174 func NewMetricGroupsCache() *MetricGroupsCache {
175 entry := &MetricGroupsCache{}
176 entry.counters = make(map[string]Counter)
177 entry.gauges = make(map[string]Gauge)
181 //-----------------------------------------------------------------------------
182 // All counters/gauges registered via Metrics instances:
183 // Counter names are build from: namespace, subsystem, metric and possible labels
184 //-----------------------------------------------------------------------------
185 var globalLock sync.Mutex
186 var cache_allcounters map[string]Counter
187 var cache_allgauges map[string]Gauge
188 var cache_allcountervects map[string]CounterVec
189 var cache_allgaugevects map[string]GaugeVec
192 cache_allcounters = make(map[string]Counter)
193 cache_allgauges = make(map[string]Gauge)
194 cache_allcountervects = make(map[string]CounterVec)
195 cache_allgaugevects = make(map[string]GaugeVec)
198 //-----------------------------------------------------------------------------
200 //-----------------------------------------------------------------------------
201 type Metrics struct {
205 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
207 url = "/ric/v1/metrics"
210 namespace = "ricxapp"
213 Logger.Info("Serving metrics on: url=%s namespace=%s", url, namespace)
215 // Expose 'metrics' endpoint with standard golang metrics used by prometheus
216 r.Handle(url, promhttp.Handler())
218 return &Metrics{Namespace: namespace}
224 func (m *Metrics) getFullName(opts prometheus.Opts, labels []string) string {
226 for _, lbl := range labels {
227 if len(labelname) == 0 {
230 labelname += "_" + lbl
233 return fmt.Sprintf("%s_%s_%s_%s", opts.Namespace, opts.Subsystem, opts.Name, labelname)
239 func (m *Metrics) RegisterCounter(opts CounterOpts, subsytem string) Counter {
241 defer globalLock.Unlock()
242 opts.Namespace = m.Namespace
243 opts.Subsystem = subsytem
244 id := m.getFullName(prometheus.Opts(opts), []string{})
245 if _, ok := cache_allcounters[id]; !ok {
246 Logger.Info("Register new counter with opts: %v", opts)
247 cache_allcounters[id] = promauto.NewCounter(prometheus.CounterOpts(opts))
249 return cache_allcounters[id]
255 func (m *Metrics) RegisterCounterGroup(optsgroup []CounterOpts, subsytem string) map[string]Counter {
256 c := make(map[string]Counter)
257 for _, opts := range optsgroup {
258 c[opts.Name] = m.RegisterCounter(opts, subsytem)
266 func (m *Metrics) RegisterLabeledCounter(opts CounterOpts, labelNames []string, labelValues []string, subsytem string) Counter {
268 defer globalLock.Unlock()
269 opts.Namespace = m.Namespace
270 opts.Subsystem = subsytem
271 vecid := m.getFullName(prometheus.Opts(opts), []string{})
272 if _, ok := cache_allcountervects[vecid]; !ok {
273 Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
274 entry := CounterVec{}
276 entry.Labels = labelNames
277 entry.Vec = promauto.NewCounterVec(prometheus.CounterOpts(entry.Opts), entry.Labels)
278 cache_allcountervects[vecid] = entry
280 entry := cache_allcountervects[vecid]
281 if strSliceCompare(entry.Labels, labelNames) == false {
282 Logger.Warn("id:%s cached counter vec labels dont match %v != %v", vecid, entry.Labels, labelNames)
285 valid := m.getFullName(prometheus.Opts(entry.Opts), labelValues)
286 if _, ok := cache_allcounters[valid]; !ok {
287 Logger.Info("Register new counter from vector with opts: %v labelValues: %v", entry.Opts, labelValues)
288 cache_allcounters[valid] = entry.Vec.WithLabelValues(labelValues...)
290 return cache_allcounters[valid]
297 func (m *Metrics) RegisterLabeledCounterGroup(optsgroup []CounterOpts, labelNames []string, labelValues []string, subsytem string) map[string]Counter {
298 c := make(map[string]Counter)
299 for _, opts := range optsgroup {
300 c[opts.Name] = m.RegisterLabeledCounter(opts, labelNames, labelValues, subsytem)
308 func (m *Metrics) RegisterGauge(opts CounterOpts, subsytem string) Gauge {
310 defer globalLock.Unlock()
311 opts.Namespace = m.Namespace
312 opts.Subsystem = subsytem
313 id := m.getFullName(prometheus.Opts(opts), []string{})
314 if _, ok := cache_allgauges[id]; !ok {
315 Logger.Info("Register new gauge with opts: %v", opts)
316 cache_allgauges[id] = promauto.NewGauge(prometheus.GaugeOpts(opts))
318 return cache_allgauges[id]
324 func (m *Metrics) RegisterGaugeGroup(optsgroup []CounterOpts, subsytem string) map[string]Gauge {
325 c := make(map[string]Gauge)
326 for _, opts := range optsgroup {
327 c[opts.Name] = m.RegisterGauge(opts, subsytem)
335 func (m *Metrics) RegisterLabeledGauge(opt CounterOpts, labelNames []string, labelValues []string, subsytem string) Gauge {
337 defer globalLock.Unlock()
338 opt.Namespace = m.Namespace
339 opt.Subsystem = subsytem
340 vecid := m.getFullName(prometheus.Opts(opt), []string{})
341 if _, ok := cache_allgaugevects[vecid]; !ok {
342 Logger.Info("Register new gauge vector with opt: %v labelNames: %v", opt, labelNames)
345 entry.Labels = labelNames
346 entry.Vec = promauto.NewGaugeVec(prometheus.GaugeOpts(entry.Opts), entry.Labels)
347 cache_allgaugevects[vecid] = entry
349 entry := cache_allgaugevects[vecid]
350 if strSliceCompare(entry.Labels, labelNames) == false {
351 Logger.Warn("id:%s cached gauge vec labels dont match %v != %v", vecid, entry.Labels, labelNames)
353 valid := m.getFullName(prometheus.Opts(entry.Opts), labelValues)
354 if _, ok := cache_allgauges[valid]; !ok {
355 Logger.Info("Register new gauge from vector with opts: %v labelValues: %v", entry.Opts, labelValues)
356 cache_allgauges[valid] = entry.Vec.WithLabelValues(labelValues...)
358 return cache_allgauges[valid]
365 func (m *Metrics) RegisterLabeledGaugeGroup(opts []CounterOpts, labelNames []string, labelValues []string, subsytem string) map[string]Gauge {
366 c := make(map[string]Gauge)
367 for _, opt := range opts {
368 c[opt.Name] = m.RegisterLabeledGauge(opt, labelNames, labelValues, subsytem)
374 * Handling counter vectors
379 vec := Metric.RegisterCounterVec(
380 CounterOpts{Name: "counter0", Help: "counter0"},
384 stat:=Metric.GetCounterFromVect([]string{"localhost:8888"},vec)
388 vec := Metric.RegisterCounterVecGroup(
390 {Name: "counter1", Help: "counter1"},
391 {Name: "counter2", Help: "counter2"},
396 stats:=Metric.GetCounterGroupFromVects([]string{"localhost:8888"}, vec)
397 stats["counter1"].Inc()
400 // Deprecated: Use RegisterLabeledCounter
401 func (m *Metrics) RegisterCounterVec(opts CounterOpts, labelNames []string, subsytem string) CounterVec {
403 defer globalLock.Unlock()
404 opts.Namespace = m.Namespace
405 opts.Subsystem = subsytem
406 id := m.getFullName(prometheus.Opts(opts), []string{})
407 if _, ok := cache_allcountervects[id]; !ok {
408 Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
409 entry := CounterVec{}
411 entry.Labels = labelNames
412 entry.Vec = promauto.NewCounterVec(prometheus.CounterOpts(entry.Opts), entry.Labels)
413 cache_allcountervects[id] = entry
415 entry := cache_allcountervects[id]
416 if strSliceCompare(entry.Labels, labelNames) == false {
417 Logger.Warn("id:%s cached counter vec labels dont match %v != %v", id, entry.Labels, labelNames)
422 // Deprecated: Use RegisterLabeledCounterGroup
423 func (m *Metrics) RegisterCounterVecGroup(optsgroup []CounterOpts, labelNames []string, subsytem string) map[string]CounterVec {
424 c := make(map[string]CounterVec)
425 for _, opts := range optsgroup {
426 c[opts.Name] = m.RegisterCounterVec(opts, labelNames, subsytem)
431 // Deprecated: Use RegisterLabeledCounter
432 func (m *Metrics) GetCounterFromVect(labelValues []string, vec CounterVec) (c Counter) {
434 defer globalLock.Unlock()
435 id := m.getFullName(prometheus.Opts(vec.Opts), labelValues)
436 if _, ok := cache_allcounters[id]; !ok {
437 Logger.Info("Register new counter from vector with opts: %v labelValues: %v", vec.Opts, labelValues)
438 cache_allcounters[id] = vec.Vec.WithLabelValues(labelValues...)
440 return cache_allcounters[id]
443 // Deprecated: Use RegisterLabeledCounterGroup
444 func (m *Metrics) GetCounterGroupFromVects(labelValues []string, vects ...map[string]CounterVec) map[string]Counter {
445 c := make(map[string]Counter)
446 for _, vect := range vects {
447 for name, vec := range vect {
448 c[name] = m.GetCounterFromVect(labelValues, vec)
454 // Deprecated: Use RegisterLabeledCounterGroup
455 func (m *Metrics) GetCounterGroupFromVectsWithPrefix(prefix string, labelValues []string, vects ...map[string]CounterVec) map[string]Counter {
456 c := make(map[string]Counter)
457 for _, vect := range vects {
458 for name, vec := range vect {
459 c[prefix+name] = m.GetCounterFromVect(labelValues, vec)
466 * Handling gauge vectors
471 vec := Metric.RegisterGaugeVec(
472 CounterOpts{Name: "gauge0", Help: "gauge0"},
476 stat:=Metric.GetGaugeFromVect([]string{"localhost:8888"},vec)
480 vecgrp := Metric.RegisterGaugeVecGroup(
482 {Name: "gauge1", Help: "gauge1"},
483 {Name: "gauge2", Help: "gauge2"},
488 stats:=Metric.GetGaugeGroupFromVects([]string{"localhost:8888"},vecgrp)
489 stats["gauge1"].Inc()
492 // Deprecated: Use RegisterLabeledGauge
493 func (m *Metrics) RegisterGaugeVec(opt CounterOpts, labelNames []string, subsytem string) GaugeVec {
495 defer globalLock.Unlock()
496 opt.Namespace = m.Namespace
497 opt.Subsystem = subsytem
498 id := m.getFullName(prometheus.Opts(opt), []string{})
499 if _, ok := cache_allgaugevects[id]; !ok {
500 Logger.Info("Register new gauge vector with opt: %v labelNames: %v", opt, labelNames)
503 entry.Labels = labelNames
504 entry.Vec = promauto.NewGaugeVec(prometheus.GaugeOpts(entry.Opts), entry.Labels)
505 cache_allgaugevects[id] = entry
507 entry := cache_allgaugevects[id]
508 if strSliceCompare(entry.Labels, labelNames) == false {
509 Logger.Warn("id:%s cached gauge vec labels dont match %v != %v", id, entry.Labels, labelNames)
514 // Deprecated: Use RegisterLabeledGaugeGroup
515 func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string, subsytem string) map[string]GaugeVec {
516 c := make(map[string]GaugeVec)
517 for _, opt := range opts {
518 c[opt.Name] = m.RegisterGaugeVec(opt, labelNames, subsytem)
523 // Deprecated: Use RegisterLabeledGauge
524 func (m *Metrics) GetGaugeFromVect(labelValues []string, vec GaugeVec) Gauge {
526 defer globalLock.Unlock()
527 id := m.getFullName(prometheus.Opts(vec.Opts), labelValues)
528 if _, ok := cache_allgauges[id]; !ok {
529 Logger.Info("Register new gauge from vector with opts: %v labelValues: %v", vec.Opts, labelValues)
530 cache_allgauges[id] = vec.Vec.WithLabelValues(labelValues...)
532 return cache_allgauges[id]
535 // Deprecated: Use RegisterLabeledGaugeGroup
536 func (m *Metrics) GetGaugeGroupFromVects(labelValues []string, vects ...map[string]GaugeVec) map[string]Gauge {
537 c := make(map[string]Gauge)
538 for _, vect := range vects {
539 for name, vec := range vect {
540 c[name] = m.GetGaugeFromVect(labelValues, vec)
546 // Deprecated: Use RegisterLabeledGaugeGroup
547 func (m *Metrics) GetGaugeGroupFromVectsWithPrefix(prefix string, labelValues []string, vects ...map[string]GaugeVec) map[string]Gauge {
548 c := make(map[string]Gauge)
549 for _, vect := range vects {
550 for name, vec := range vect {
551 c[prefix+name] = m.GetGaugeFromVect(labelValues, vec)