Support to prometheus CounterVec and GaugeVec.
[ric-plt/xapp-frame.git] / pkg / xapp / metrics.go
1 /*
2 ==================================================================================
3   Copyright (c) 2019 AT&T Intellectual Property.
4   Copyright (c) 2019 Nokia
5
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
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
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 ==================================================================================
18 */
19
20 package xapp
21
22 import (
23         "github.com/gorilla/mux"
24         "github.com/prometheus/client_golang/prometheus"
25         "github.com/prometheus/client_golang/prometheus/promauto"
26         "github.com/prometheus/client_golang/prometheus/promhttp"
27 )
28
29 type Metrics struct {
30         Namespace string
31 }
32
33 // Alias
34 type CounterOpts prometheus.Opts
35 type Counter prometheus.Counter
36 type Gauge prometheus.Gauge
37
38 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
39         if url == "" {
40                 url = "/ric/v1/metrics"
41         }
42         if namespace == "" {
43                 namespace = "ricxapp"
44         }
45
46         Logger.Info("Serving metrics on: url=%s namespace=%s", url, namespace)
47
48         // Expose 'metrics' endpoint with standard golang metrics used by prometheus
49         r.Handle(url, promhttp.Handler())
50
51         return &Metrics{Namespace: namespace}
52 }
53
54 /*
55  * Handling counters
56  */
57 func (m *Metrics) registerCounter(opts CounterOpts) Counter {
58         Logger.Info("Register new counter with opts: %v", opts)
59         return promauto.NewCounter(prometheus.CounterOpts(opts))
60 }
61
62 func (m *Metrics) RegisterCounterGroup(opts []CounterOpts, subsytem string) (c map[string]Counter) {
63         c = make(map[string]Counter)
64         for _, opt := range opts {
65                 opt.Namespace = m.Namespace
66                 opt.Subsystem = subsytem
67                 c[opt.Name] = m.registerCounter(opt)
68         }
69
70         return
71 }
72
73 /*
74  * Handling gauges
75  */
76 func (m *Metrics) registerGauge(opts CounterOpts) Gauge {
77         Logger.Info("Register new gauge with opts: %v", opts)
78         return promauto.NewGauge(prometheus.GaugeOpts(opts))
79 }
80
81 func (m *Metrics) RegisterGaugeGroup(opts []CounterOpts, subsytem string) (c map[string]Gauge) {
82         c = make(map[string]Gauge)
83         for _, opt := range opts {
84                 opt.Namespace = m.Namespace
85                 opt.Subsystem = subsytem
86                 c[opt.Name] = m.registerGauge(opt)
87         }
88
89         return
90 }
91
92 /*
93  * Handling counter vectors
94  *
95  * Example:
96
97         vec := Metric.RegisterCounterVecGroup(
98                 []CounterOpts{
99                         {Name: "counter1", Help: "counter1"},
100                         {Name: "counter2", Help: "counter2"},
101                 },
102                 []string{"host"},
103                 "SUBSYSTEM")
104
105         stat:=Metric.GetCounterGroupFromVects([]string{"localhost:8888"}, vec)
106
107 */
108 type CounterVec struct {
109         Vec  *prometheus.CounterVec
110         Opts CounterOpts
111 }
112
113 func (m *Metrics) registerCounterVec(opts CounterOpts, labelNames []string) *prometheus.CounterVec {
114         Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
115
116         return promauto.NewCounterVec(prometheus.CounterOpts(opts), labelNames)
117 }
118
119 func (m *Metrics) RegisterCounterVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]CounterVec) {
120         c = make(map[string]CounterVec)
121         for _, opt := range opts {
122                 entry := CounterVec{}
123                 entry.Opts = opt
124                 entry.Opts.Namespace = m.Namespace
125                 entry.Opts.Subsystem = subsytem
126                 entry.Vec = m.registerCounterVec(entry.Opts, labelNames)
127                 c[opt.Name] = entry
128         }
129         return
130 }
131
132 func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
133         c = make(map[string]Counter)
134         for _, vec := range vects {
135                 for name, opt := range vec {
136                         c[name] = opt.Vec.WithLabelValues(labels...)
137                         Logger.Info("Register new counter for vector with opts: %v labels: %v", opt.Opts, labels)
138                 }
139         }
140         return
141 }
142
143 /*
144  * Handling gauge vectors
145  *
146  * Example:
147
148         vec := Metric.RegisterGaugeVecGroup(
149                 []CounterOpts{
150                         {Name: "gauge1", Help: "gauge1"},
151                         {Name: "gauge2", Help: "gauge2"},
152                 },
153                 []string{"host"},
154                 "SUBSYSTEM")
155
156         stat:=Metric.GetGaugeGroupFromVects([]string{"localhost:8888"},vec)
157
158 */
159 type GaugeVec struct {
160         Vec  *prometheus.GaugeVec
161         Opts CounterOpts
162 }
163
164 func (m *Metrics) registerGaugeVec(opts CounterOpts, labelNames []string) *prometheus.GaugeVec {
165         Logger.Info("Register new gauge vector with opts: %v labelNames: %v", opts, labelNames)
166
167         return promauto.NewGaugeVec(prometheus.GaugeOpts(opts), labelNames)
168 }
169
170 func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]GaugeVec) {
171         c = make(map[string]GaugeVec)
172         for _, opt := range opts {
173                 entry := GaugeVec{}
174                 entry.Opts = opt
175                 entry.Opts.Namespace = m.Namespace
176                 entry.Opts.Subsystem = subsytem
177                 entry.Vec = m.registerGaugeVec(entry.Opts, labelNames)
178                 c[opt.Name] = entry
179
180         }
181         return
182 }
183
184 func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
185         c = make(map[string]Gauge)
186         for _, vec := range vects {
187                 for name, opt := range vec {
188                         c[name] = opt.Vec.WithLabelValues(labels...)
189                         Logger.Info("Register new gauge for vector with opts: %v labels: %v", opt.Opts, labels)
190                 }
191         }
192         return
193 }
194
195 /*
196  *
197  */
198 func (m *Metrics) CombineCounterGroups(srcs ...map[string]Counter) map[string]Counter {
199         trg := make(map[string]Counter)
200         for _, src := range srcs {
201                 for k, v := range src {
202                         trg[k] = v
203                 }
204         }
205         return trg
206 }
207
208 func (m *Metrics) CombineGaugeGroups(srcs ...map[string]Gauge) map[string]Gauge {
209         trg := make(map[string]Gauge)
210         for _, src := range srcs {
211                 for k, v := range src {
212                         trg[k] = v
213                 }
214         }
215         return trg
216 }