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) CInc(metric string) {
58 met.counters[metric].Inc()
61 func (met *MetricGroupsCache) CAdd(metric string, val float64) {
64 met.counters[metric].Add(val)
67 func (met *MetricGroupsCache) GIs(metric string) bool {
70 _, ok := met.gauges[metric]
74 func (met *MetricGroupsCache) GSet(metric string, val float64) {
77 met.gauges[metric].Set(val)
80 func (met *MetricGroupsCache) GInc(metric string) {
83 met.gauges[metric].Inc()
86 func (met *MetricGroupsCache) GDec(metric string) {
89 met.gauges[metric].Dec()
92 func (met *MetricGroupsCache) CombineCounterGroups(srcs ...map[string]Counter) {
95 for _, src := range srcs {
96 for k, v := range src {
102 func (met *MetricGroupsCache) CombineGaugeGroups(srcs ...map[string]Gauge) {
105 for _, src := range srcs {
106 for k, v := range src {
112 func NewMetricGroupsCache() *MetricGroupsCache {
113 entry := &MetricGroupsCache{}
114 entry.counters = make(map[string]Counter)
115 entry.gauges = make(map[string]Gauge)
119 //-----------------------------------------------------------------------------
120 // All counters/gauges registered via Metrics instances:
121 // Counter names are build from: namespace, subsystem, metric and possible labels
122 //-----------------------------------------------------------------------------
123 var globalLock sync.Mutex
124 var cache_allcounters map[string]Counter
125 var cache_allgauges map[string]Gauge
128 cache_allcounters = make(map[string]Counter)
129 cache_allgauges = make(map[string]Gauge)
132 //-----------------------------------------------------------------------------
134 //-----------------------------------------------------------------------------
135 type Metrics struct {
139 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
141 url = "/ric/v1/metrics"
144 namespace = "ricxapp"
147 Logger.Info("Serving metrics on: url=%s namespace=%s", url, namespace)
149 // Expose 'metrics' endpoint with standard golang metrics used by prometheus
150 r.Handle(url, promhttp.Handler())
152 return &Metrics{Namespace: namespace}
158 func (m *Metrics) getFullName(opts prometheus.Opts, labels []string) string {
160 for _, lbl := range labels {
161 if len(labelname) == 0 {
164 labelname += "_" + lbl
167 return fmt.Sprintf("%s_%s_%s_%s", opts.Namespace, opts.Subsystem, opts.Name, labelname)
173 func (m *Metrics) registerCounter(opts CounterOpts) Counter {
174 Logger.Info("Register new counter with opts: %v", opts)
175 return promauto.NewCounter(prometheus.CounterOpts(opts))
178 func (m *Metrics) RegisterCounterGroup(opts []CounterOpts, subsytem string) (c map[string]Counter) {
180 defer globalLock.Unlock()
181 c = make(map[string]Counter)
182 for _, opt := range opts {
183 opt.Namespace = m.Namespace
184 opt.Subsystem = subsytem
186 id := m.getFullName(prometheus.Opts(opt), []string{})
187 if _, ok := cache_allcounters[id]; !ok {
188 cache_allcounters[id] = m.registerCounter(opt)
191 c[opt.Name] = cache_allcounters[id]
200 func (m *Metrics) registerGauge(opts CounterOpts) Gauge {
201 Logger.Info("Register new gauge with opts: %v", opts)
202 return promauto.NewGauge(prometheus.GaugeOpts(opts))
205 func (m *Metrics) RegisterGaugeGroup(opts []CounterOpts, subsytem string) (c map[string]Gauge) {
207 defer globalLock.Unlock()
208 c = make(map[string]Gauge)
209 for _, opt := range opts {
210 opt.Namespace = m.Namespace
211 opt.Subsystem = subsytem
213 id := m.getFullName(prometheus.Opts(opt), []string{})
214 if _, ok := cache_allgauges[id]; !ok {
215 cache_allgauges[id] = m.registerGauge(opt)
218 c[opt.Name] = cache_allgauges[id]
225 * Handling counter vectors
229 vec := Metric.RegisterCounterVecGroup(
231 {Name: "counter1", Help: "counter1"},
232 {Name: "counter2", Help: "counter2"},
237 stat:=Metric.GetCounterGroupFromVects([]string{"localhost:8888"}, vec)
240 type CounterVec struct {
241 Vec *prometheus.CounterVec
245 func (m *Metrics) registerCounterVec(opts CounterOpts, labelNames []string) *prometheus.CounterVec {
246 Logger.Info("Register new counter vector with opts: %v labelNames: %v", opts, labelNames)
247 return promauto.NewCounterVec(prometheus.CounterOpts(opts), labelNames)
250 func (m *Metrics) RegisterCounterVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]CounterVec) {
251 c = make(map[string]CounterVec)
252 for _, opt := range opts {
253 entry := CounterVec{}
255 entry.Opts.Namespace = m.Namespace
256 entry.Opts.Subsystem = subsytem
257 entry.Vec = m.registerCounterVec(entry.Opts, labelNames)
263 func (m *Metrics) GetCounterGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
265 defer globalLock.Unlock()
266 c = make(map[string]Counter)
267 for _, vec := range vects {
268 for name, opt := range vec {
270 id := m.getFullName(prometheus.Opts(opt.Opts), labels)
271 if _, ok := cache_allcounters[id]; !ok {
272 Logger.Info("Register new counter from vector with opts: %v labels: %v prefix: %s", opt.Opts, labels, prefix)
273 cache_allcounters[id] = opt.Vec.WithLabelValues(labels...)
275 c[prefix+name] = cache_allcounters[id]
281 func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
282 return m.GetCounterGroupFromVectsWithPrefix("", labels, vects...)
286 * Handling gauge vectors
290 vec := Metric.RegisterGaugeVecGroup(
292 {Name: "gauge1", Help: "gauge1"},
293 {Name: "gauge2", Help: "gauge2"},
298 stat:=Metric.GetGaugeGroupFromVects([]string{"localhost:8888"},vec)
301 type GaugeVec struct {
302 Vec *prometheus.GaugeVec
306 func (m *Metrics) registerGaugeVec(opts CounterOpts, labelNames []string) *prometheus.GaugeVec {
307 Logger.Info("Register new gauge vector with opts: %v labelNames: %v", opts, labelNames)
308 return promauto.NewGaugeVec(prometheus.GaugeOpts(opts), labelNames)
311 func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string, subsytem string) (c map[string]GaugeVec) {
312 c = make(map[string]GaugeVec)
313 for _, opt := range opts {
316 entry.Opts.Namespace = m.Namespace
317 entry.Opts.Subsystem = subsytem
318 entry.Vec = m.registerGaugeVec(entry.Opts, labelNames)
325 func (m *Metrics) GetGaugeGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
327 defer globalLock.Unlock()
328 c = make(map[string]Gauge)
329 for _, vec := range vects {
330 for name, opt := range vec {
332 id := m.getFullName(prometheus.Opts(opt.Opts), labels)
333 if _, ok := cache_allgauges[id]; !ok {
334 Logger.Info("Register new gauge from vector with opts: %v labels: %v prefix: %s", opt.Opts, labels, prefix)
335 cache_allgauges[id] = opt.Vec.WithLabelValues(labels...)
337 c[prefix+name] = cache_allgauges[id]
343 func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
344 return m.GetGaugeGroupFromVectsWithPrefix("", labels, vects...)