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 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
42 type MetricGroupsCache struct {
43 sync.RWMutex //This is for map locking
44 counters map[string]Counter
45 gauges map[string]Gauge
48 func (met *MetricGroupsCache) CIs(metric string) bool {
51 _, ok := met.counters[metric]
55 func (met *MetricGroupsCache) CGet(metric string) Counter {
58 return met.counters[metric]
61 func (met *MetricGroupsCache) CInc(metric string) {
64 met.counters[metric].Inc()
67 func (met *MetricGroupsCache) CAdd(metric string, val float64) {
70 met.counters[metric].Add(val)
73 func (met *MetricGroupsCache) GIs(metric string) bool {
76 _, ok := met.gauges[metric]
80 func (met *MetricGroupsCache) GGet(metric string) Gauge {
83 return met.gauges[metric]
86 func (met *MetricGroupsCache) GSet(metric string, val float64) {
89 met.gauges[metric].Set(val)
92 func (met *MetricGroupsCache) GInc(metric string) {
95 met.gauges[metric].Inc()
98 func (met *MetricGroupsCache) GDec(metric string) {
101 met.gauges[metric].Dec()
104 func (met *MetricGroupsCache) CombineCounterGroups(srcs ...map[string]Counter) {
107 for _, src := range srcs {
108 for k, v := range src {
114 func (met *MetricGroupsCache) CombineGaugeGroups(srcs ...map[string]Gauge) {
117 for _, src := range srcs {
118 for k, v := range src {
124 func NewMetricGroupsCache() *MetricGroupsCache {
125 entry := &MetricGroupsCache{}
126 entry.counters = make(map[string]Counter)
127 entry.gauges = make(map[string]Gauge)
131 //-----------------------------------------------------------------------------
132 // All counters/gauges registered via Metrics instances:
133 // Counter names are build from: namespace, subsystem, metric and possible labels
134 //-----------------------------------------------------------------------------
135 var globalLock sync.Mutex
136 var cache_allcounters map[string]Counter
137 var cache_allgauges map[string]Gauge
140 cache_allcounters = make(map[string]Counter)
141 cache_allgauges = make(map[string]Gauge)
144 //-----------------------------------------------------------------------------
146 //-----------------------------------------------------------------------------
147 type Metrics struct {
151 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
153 url = "/ric/v1/metrics"
156 namespace = "ricxapp"
159 Logger.Info("Serving metrics on: url=%s namespace=%s", url, namespace)
161 // Expose 'metrics' endpoint with standard golang metrics used by prometheus
162 r.Handle(url, promhttp.Handler())
164 return &Metrics{Namespace: namespace}
170 func (m *Metrics) getFullName(opts prometheus.Opts, labels []string) string {
172 for _, lbl := range labels {
173 if len(labelname) == 0 {
176 labelname += "_" + lbl
179 return fmt.Sprintf("%s_%s_%s_%s", opts.Namespace, opts.Subsystem, opts.Name, labelname)
185 func (m *Metrics) registerCounter(opts CounterOpts) Counter {
186 Logger.Info("Register new counter with opts: %v", opts)
187 return promauto.NewCounter(prometheus.CounterOpts(opts))
190 func (m *Metrics) RegisterCounterGroup(opts []CounterOpts, subsytem string) (c map[string]Counter) {
192 defer globalLock.Unlock()
193 c = make(map[string]Counter)
194 for _, opt := range opts {
195 opt.Namespace = m.Namespace
196 opt.Subsystem = subsytem
198 id := m.getFullName(prometheus.Opts(opt), []string{})
199 if _, ok := cache_allcounters[id]; !ok {
200 cache_allcounters[id] = m.registerCounter(opt)
203 c[opt.Name] = cache_allcounters[id]
212 func (m *Metrics) registerGauge(opts CounterOpts) Gauge {
213 Logger.Info("Register new gauge with opts: %v", opts)
214 return promauto.NewGauge(prometheus.GaugeOpts(opts))
217 func (m *Metrics) RegisterGaugeGroup(opts []CounterOpts, subsytem string) (c map[string]Gauge) {
219 defer globalLock.Unlock()
220 c = make(map[string]Gauge)
221 for _, opt := range opts {
222 opt.Namespace = m.Namespace
223 opt.Subsystem = subsytem
225 id := m.getFullName(prometheus.Opts(opt), []string{})
226 if _, ok := cache_allgauges[id]; !ok {
227 cache_allgauges[id] = m.registerGauge(opt)
230 c[opt.Name] = cache_allgauges[id]
237 * Handling counter vectors
241 vec := Metric.RegisterCounterVecGroup(
243 {Name: "counter1", Help: "counter1"},
244 {Name: "counter2", Help: "counter2"},
249 stat:=Metric.GetCounterGroupFromVects([]string{"localhost:8888"}, vec)
252 type CounterVec struct {
253 Vec *prometheus.CounterVec
257 func (m *Metrics) registerCounterVec(opts CounterOpts, labelNames []string) *prometheus.CounterVec {
258 Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
259 return promauto.NewCounterVec(prometheus.CounterOpts(opts), labelNames)
262 func (m *Metrics) RegisterCounterVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]CounterVec) {
263 c = make(map[string]CounterVec)
264 for _, opt := range opts {
265 entry := CounterVec{}
267 entry.Opts.Namespace = m.Namespace
268 entry.Opts.Subsystem = subsytem
269 entry.Vec = m.registerCounterVec(entry.Opts, labelNames)
275 func (m *Metrics) GetCounterGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
277 defer globalLock.Unlock()
278 c = make(map[string]Counter)
279 for _, vec := range vects {
280 for name, opt := range vec {
282 id := m.getFullName(prometheus.Opts(opt.Opts), labels)
283 if _, ok := cache_allcounters[id]; !ok {
284 Logger.Info("Register new counter from vector with opts: %v labels: %v prefix: %s", opt.Opts, labels, prefix)
285 cache_allcounters[id] = opt.Vec.WithLabelValues(labels...)
287 c[prefix+name] = cache_allcounters[id]
293 func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
294 return m.GetCounterGroupFromVectsWithPrefix("", labels, vects...)
298 * Handling gauge vectors
302 vec := Metric.RegisterGaugeVecGroup(
304 {Name: "gauge1", Help: "gauge1"},
305 {Name: "gauge2", Help: "gauge2"},
310 stat:=Metric.GetGaugeGroupFromVects([]string{"localhost:8888"},vec)
313 type GaugeVec struct {
314 Vec *prometheus.GaugeVec
318 func (m *Metrics) registerGaugeVec(opts CounterOpts, labelNames []string) *prometheus.GaugeVec {
319 Logger.Info("Register new gauge vector with opts: %v labelNames: %v", opts, labelNames)
320 return promauto.NewGaugeVec(prometheus.GaugeOpts(opts), labelNames)
323 func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]GaugeVec) {
324 c = make(map[string]GaugeVec)
325 for _, opt := range opts {
328 entry.Opts.Namespace = m.Namespace
329 entry.Opts.Subsystem = subsytem
330 entry.Vec = m.registerGaugeVec(entry.Opts, labelNames)
337 func (m *Metrics) GetGaugeGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
339 defer globalLock.Unlock()
340 c = make(map[string]Gauge)
341 for _, vec := range vects {
342 for name, opt := range vec {
344 id := m.getFullName(prometheus.Opts(opt.Opts), labels)
345 if _, ok := cache_allgauges[id]; !ok {
346 Logger.Info("Register new gauge from vector with opts: %v labels: %v prefix: %s", opt.Opts, labels, prefix)
347 cache_allgauges[id] = opt.Vec.WithLabelValues(labels...)
349 c[prefix+name] = cache_allgauges[id]
355 func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
356 return m.GetGaugeGroupFromVectsWithPrefix("", labels, vects...)