c943db6bb61cdd6040aec2da60fec1531d11fe78
[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 //-----------------------------------------------------------------------------
30 // Alias
31 //-----------------------------------------------------------------------------
32 type CounterOpts prometheus.Opts
33 type Counter prometheus.Counter
34 type Gauge prometheus.Gauge
35
36 //-----------------------------------------------------------------------------
37 //
38 //-----------------------------------------------------------------------------
39
40 type MetricGroupsCache struct {
41         Counters map[string]Counter
42         Gauges   map[string]Gauge
43 }
44
45 func (met *MetricGroupsCache) CInc(metric string) {
46         met.Counters[metric].Inc()
47 }
48
49 func (met *MetricGroupsCache) CAdd(metric string, val float64) {
50         met.Counters[metric].Add(val)
51 }
52
53 func (met *MetricGroupsCache) GSet(metric string, val float64) {
54         met.Gauges[metric].Set(val)
55 }
56
57 //-----------------------------------------------------------------------------
58 //
59 //-----------------------------------------------------------------------------
60 type Metrics struct {
61         Namespace            string
62         MetricGroupsCacheMap map[string]*MetricGroupsCache
63 }
64
65 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
66         if url == "" {
67                 url = "/ric/v1/metrics"
68         }
69         if namespace == "" {
70                 namespace = "ricxapp"
71         }
72
73         Logger.Info("Serving metrics on: url=%s namespace=%s", url, namespace)
74
75         // Expose 'metrics' endpoint with standard golang metrics used by prometheus
76         r.Handle(url, promhttp.Handler())
77
78         return &Metrics{Namespace: namespace, MetricGroupsCacheMap: make(map[string]*MetricGroupsCache)}
79 }
80
81 /*
82  * Handling counters
83  */
84 func (m *Metrics) registerCounter(opts CounterOpts) Counter {
85         Logger.Info("Register new counter with opts: %v", opts)
86         return promauto.NewCounter(prometheus.CounterOpts(opts))
87 }
88
89 func (m *Metrics) RegisterCounterGroup(opts []CounterOpts, subsytem string) (c map[string]Counter) {
90         c = make(map[string]Counter)
91         for _, opt := range opts {
92                 opt.Namespace = m.Namespace
93                 opt.Subsystem = subsytem
94                 c[opt.Name] = m.registerCounter(opt)
95         }
96
97         return
98 }
99
100 /*
101  * Handling gauges
102  */
103 func (m *Metrics) registerGauge(opts CounterOpts) Gauge {
104         Logger.Info("Register new gauge with opts: %v", opts)
105         return promauto.NewGauge(prometheus.GaugeOpts(opts))
106 }
107
108 func (m *Metrics) RegisterGaugeGroup(opts []CounterOpts, subsytem string) (c map[string]Gauge) {
109         c = make(map[string]Gauge)
110         for _, opt := range opts {
111                 opt.Namespace = m.Namespace
112                 opt.Subsystem = subsytem
113                 c[opt.Name] = m.registerGauge(opt)
114         }
115
116         return
117 }
118
119 /*
120  * Handling counter vectors
121  *
122  * Example:
123
124         vec := Metric.RegisterCounterVecGroup(
125                 []CounterOpts{
126                         {Name: "counter1", Help: "counter1"},
127                         {Name: "counter2", Help: "counter2"},
128                 },
129                 []string{"host"},
130                 "SUBSYSTEM")
131
132         stat:=Metric.GetCounterGroupFromVects([]string{"localhost:8888"}, vec)
133
134 */
135 type CounterVec struct {
136         Vec  *prometheus.CounterVec
137         Opts CounterOpts
138 }
139
140 func (m *Metrics) registerCounterVec(opts CounterOpts, labelNames []string) *prometheus.CounterVec {
141         Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
142
143         return promauto.NewCounterVec(prometheus.CounterOpts(opts), labelNames)
144 }
145
146 func (m *Metrics) RegisterCounterVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]CounterVec) {
147         c = make(map[string]CounterVec)
148         for _, opt := range opts {
149                 entry := CounterVec{}
150                 entry.Opts = opt
151                 entry.Opts.Namespace = m.Namespace
152                 entry.Opts.Subsystem = subsytem
153                 entry.Vec = m.registerCounterVec(entry.Opts, labelNames)
154                 c[opt.Name] = entry
155         }
156         return
157 }
158
159 func (m *Metrics) GetCounterGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
160         c = make(map[string]Counter)
161         for _, vec := range vects {
162                 for name, opt := range vec {
163                         c[prefix+name] = opt.Vec.WithLabelValues(labels...)
164                         Logger.Info("Register new counter for vector with opts: %v labels: %v", opt.Opts, labels)
165                 }
166         }
167         return
168 }
169
170 func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
171         return m.GetCounterGroupFromVectsWithPrefix("", labels, vects...)
172 }
173
174 /*
175  * Handling gauge vectors
176  *
177  * Example:
178
179         vec := Metric.RegisterGaugeVecGroup(
180                 []CounterOpts{
181                         {Name: "gauge1", Help: "gauge1"},
182                         {Name: "gauge2", Help: "gauge2"},
183                 },
184                 []string{"host"},
185                 "SUBSYSTEM")
186
187         stat:=Metric.GetGaugeGroupFromVects([]string{"localhost:8888"},vec)
188
189 */
190 type GaugeVec struct {
191         Vec  *prometheus.GaugeVec
192         Opts CounterOpts
193 }
194
195 func (m *Metrics) registerGaugeVec(opts CounterOpts, labelNames []string) *prometheus.GaugeVec {
196         Logger.Info("Register new gauge vector with opts: %v labelNames: %v", opts, labelNames)
197
198         return promauto.NewGaugeVec(prometheus.GaugeOpts(opts), labelNames)
199 }
200
201 func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]GaugeVec) {
202         c = make(map[string]GaugeVec)
203         for _, opt := range opts {
204                 entry := GaugeVec{}
205                 entry.Opts = opt
206                 entry.Opts.Namespace = m.Namespace
207                 entry.Opts.Subsystem = subsytem
208                 entry.Vec = m.registerGaugeVec(entry.Opts, labelNames)
209                 c[opt.Name] = entry
210
211         }
212         return
213 }
214
215 func (m *Metrics) GetGaugeGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
216         c = make(map[string]Gauge)
217         for _, vec := range vects {
218                 for name, opt := range vec {
219                         c[prefix+name] = opt.Vec.WithLabelValues(labels...)
220                         Logger.Info("Register new gauge for vector with opts: %v labels: %v", opt.Opts, labels)
221                 }
222         }
223         return
224 }
225
226 func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
227         return m.GetGaugeGroupFromVectsWithPrefix("", labels, vects...)
228
229 }
230
231 /*
232  *
233  */
234 func (m *Metrics) CombineCounterGroups(srcs ...map[string]Counter) map[string]Counter {
235         trg := make(map[string]Counter)
236         for _, src := range srcs {
237                 for k, v := range src {
238                         trg[k] = v
239                 }
240         }
241         return trg
242 }
243
244 func (m *Metrics) CombineGaugeGroups(srcs ...map[string]Gauge) map[string]Gauge {
245         trg := make(map[string]Gauge)
246         for _, src := range srcs {
247                 for k, v := range src {
248                         trg[k] = v
249                 }
250         }
251         return trg
252 }
253
254 /*
255  *
256  */
257 func (m *Metrics) GroupCacheGet(id string) *MetricGroupsCache {
258         entry, ok := m.MetricGroupsCacheMap[id]
259         if ok == false {
260                 return nil
261         }
262         return entry
263 }
264
265 func (m *Metrics) GroupCacheAddCounters(id string, vals map[string]Counter) {
266         entry, ok := m.MetricGroupsCacheMap[id]
267         if ok == false {
268                 entry = &MetricGroupsCache{}
269                 m.MetricGroupsCacheMap[id] = entry
270         }
271         m.MetricGroupsCacheMap[id].Counters = m.CombineCounterGroups(m.MetricGroupsCacheMap[id].Counters, vals)
272 }
273
274 func (m *Metrics) GroupCacheAddGauges(id string, vals map[string]Gauge) {
275         entry, ok := m.MetricGroupsCacheMap[id]
276         if ok == false {
277                 entry = &MetricGroupsCache{}
278                 m.MetricGroupsCacheMap[id] = entry
279         }
280         m.MetricGroupsCacheMap[id].Gauges = m.CombineGaugeGroups(m.MetricGroupsCacheMap[id].Gauges, vals)
281 }