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) GAdd(metric string, val float64) {
95 met.gauges[metric].Add(val)
98 func (met *MetricGroupsCache) GInc(metric string) {
101 met.gauges[metric].Inc()
104 func (met *MetricGroupsCache) GDec(metric string) {
107 met.gauges[metric].Dec()
110 func (met *MetricGroupsCache) CombineCounterGroups(srcs ...map[string]Counter) {
113 for _, src := range srcs {
114 for k, v := range src {
120 func (met *MetricGroupsCache) CombineGaugeGroups(srcs ...map[string]Gauge) {
123 for _, src := range srcs {
124 for k, v := range src {
130 func NewMetricGroupsCache() *MetricGroupsCache {
131 entry := &MetricGroupsCache{}
132 entry.counters = make(map[string]Counter)
133 entry.gauges = make(map[string]Gauge)
137 //-----------------------------------------------------------------------------
138 // All counters/gauges registered via Metrics instances:
139 // Counter names are build from: namespace, subsystem, metric and possible labels
140 //-----------------------------------------------------------------------------
141 var globalLock sync.Mutex
142 var cache_allcounters map[string]Counter
143 var cache_allgauges map[string]Gauge
146 cache_allcounters = make(map[string]Counter)
147 cache_allgauges = make(map[string]Gauge)
150 //-----------------------------------------------------------------------------
152 //-----------------------------------------------------------------------------
153 type Metrics struct {
157 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
159 url = "/ric/v1/metrics"
162 namespace = "ricxapp"
165 Logger.Info("Serving metrics on: url=%s namespace=%s", url, namespace)
167 // Expose 'metrics' endpoint with standard golang metrics used by prometheus
168 r.Handle(url, promhttp.Handler())
170 return &Metrics{Namespace: namespace}
176 func (m *Metrics) getFullName(opts prometheus.Opts, labels []string) string {
178 for _, lbl := range labels {
179 if len(labelname) == 0 {
182 labelname += "_" + lbl
185 return fmt.Sprintf("%s_%s_%s_%s", opts.Namespace, opts.Subsystem, opts.Name, labelname)
191 func (m *Metrics) registerCounter(opts CounterOpts) Counter {
192 Logger.Info("Register new counter with opts: %v", opts)
193 return promauto.NewCounter(prometheus.CounterOpts(opts))
196 func (m *Metrics) RegisterCounterGroup(opts []CounterOpts, subsytem string) (c map[string]Counter) {
198 defer globalLock.Unlock()
199 c = make(map[string]Counter)
200 for _, opt := range opts {
201 opt.Namespace = m.Namespace
202 opt.Subsystem = subsytem
204 id := m.getFullName(prometheus.Opts(opt), []string{})
205 if _, ok := cache_allcounters[id]; !ok {
206 cache_allcounters[id] = m.registerCounter(opt)
209 c[opt.Name] = cache_allcounters[id]
218 func (m *Metrics) registerGauge(opts CounterOpts) Gauge {
219 Logger.Info("Register new gauge with opts: %v", opts)
220 return promauto.NewGauge(prometheus.GaugeOpts(opts))
223 func (m *Metrics) RegisterGaugeGroup(opts []CounterOpts, subsytem string) (c map[string]Gauge) {
225 defer globalLock.Unlock()
226 c = make(map[string]Gauge)
227 for _, opt := range opts {
228 opt.Namespace = m.Namespace
229 opt.Subsystem = subsytem
231 id := m.getFullName(prometheus.Opts(opt), []string{})
232 if _, ok := cache_allgauges[id]; !ok {
233 cache_allgauges[id] = m.registerGauge(opt)
236 c[opt.Name] = cache_allgauges[id]
243 * Handling counter vectors
247 vec := Metric.RegisterCounterVecGroup(
249 {Name: "counter1", Help: "counter1"},
250 {Name: "counter2", Help: "counter2"},
255 stat:=Metric.GetCounterGroupFromVects([]string{"localhost:8888"}, vec)
258 type CounterVec struct {
259 Vec *prometheus.CounterVec
263 func (m *Metrics) registerCounterVec(opts CounterOpts, labelNames []string) *prometheus.CounterVec {
264 Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
265 return promauto.NewCounterVec(prometheus.CounterOpts(opts), labelNames)
268 func (m *Metrics) RegisterCounterVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]CounterVec) {
269 c = make(map[string]CounterVec)
270 for _, opt := range opts {
271 entry := CounterVec{}
273 entry.Opts.Namespace = m.Namespace
274 entry.Opts.Subsystem = subsytem
275 entry.Vec = m.registerCounterVec(entry.Opts, labelNames)
281 func (m *Metrics) GetCounterGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
283 defer globalLock.Unlock()
284 c = make(map[string]Counter)
285 for _, vec := range vects {
286 for name, opt := range vec {
288 id := m.getFullName(prometheus.Opts(opt.Opts), labels)
289 if _, ok := cache_allcounters[id]; !ok {
290 Logger.Info("Register new counter from vector with opts: %v labels: %v prefix: %s", opt.Opts, labels, prefix)
291 cache_allcounters[id] = opt.Vec.WithLabelValues(labels...)
293 c[prefix+name] = cache_allcounters[id]
299 func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
300 return m.GetCounterGroupFromVectsWithPrefix("", labels, vects...)
304 * Handling gauge vectors
308 vec := Metric.RegisterGaugeVecGroup(
310 {Name: "gauge1", Help: "gauge1"},
311 {Name: "gauge2", Help: "gauge2"},
316 stat:=Metric.GetGaugeGroupFromVects([]string{"localhost:8888"},vec)
319 type GaugeVec struct {
320 Vec *prometheus.GaugeVec
324 func (m *Metrics) registerGaugeVec(opts CounterOpts, labelNames []string) *prometheus.GaugeVec {
325 Logger.Info("Register new gauge vector with opts: %v labelNames: %v", opts, labelNames)
326 return promauto.NewGaugeVec(prometheus.GaugeOpts(opts), labelNames)
329 func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]GaugeVec) {
330 c = make(map[string]GaugeVec)
331 for _, opt := range opts {
334 entry.Opts.Namespace = m.Namespace
335 entry.Opts.Subsystem = subsytem
336 entry.Vec = m.registerGaugeVec(entry.Opts, labelNames)
343 func (m *Metrics) GetGaugeGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
345 defer globalLock.Unlock()
346 c = make(map[string]Gauge)
347 for _, vec := range vects {
348 for name, opt := range vec {
350 id := m.getFullName(prometheus.Opts(opt.Opts), labels)
351 if _, ok := cache_allgauges[id]; !ok {
352 Logger.Info("Register new gauge from vector with opts: %v labels: %v prefix: %s", opt.Opts, labels, prefix)
353 cache_allgauges[id] = opt.Vec.WithLabelValues(labels...)
355 c[prefix+name] = cache_allgauges[id]
361 func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
362 return m.GetGaugeGroupFromVectsWithPrefix("", labels, vects...)