========= 39/3639/4
authorJuha Hyttinen <juha.hyttinen@nokia.com>
Fri, 8 May 2020 09:17:05 +0000 (12:17 +0300)
committerJuha Hyttinen <juha.hyttinen@nokia.com>
Fri, 8 May 2020 11:09:48 +0000 (14:09 +0300)
Added support for name prefix when creating group from vector

Example:
vect:=RegisterCounterVecGroup(
[]CounterOpts{{Name: "counter", Help: "counter"},},
[]string{"name", "event"},
"SUBSSYSTEM")

grp1:=GetCounterGroupFromVectsWithPrefix("event1_", []string{"name1", "event1"}, vect)
grp2:=GetCounterGroupFromVectsWithPrefix("event2_", []string{"name1", "event2"}, vect)
grp:=CombineCounterGroups(grp1,grp2)

grp["event1_counter"].Inc() -> increments "counter" (NAMESPACE_SUBSYSTEM_counter) with labels: "name=name1", "event=event1"
grp["event2_counter"].Inc() -> increments "counter" (NAMESPACE_SUBSYSTEM_counter) with labels: "name=name1", "event=event2"

=========
Added cache support for created metric groups

Example (uses prev example groups):

cacheid := "CACHEID"
entry := xapp.Metric.GroupCacheGet(cacheid)
if entry == nil {
xapp.Metric.GroupCacheAddCounters(cacheid, grp1)
xapp.Metric.GroupCacheAddCounters(cacheid, grp2)
entry = xapp.Metric.GroupCacheGet(cacheid)
}
entry.Counters["event1_counter"].Inc() -> increments "counter" (NAMESPACE_SUBSYSTEM_counter) with labels: "name=name1", "event=event1"
entry.Counters["event2_counter"].Inc() -> increments "counter" (NAMESPACE_SUBSYSTEM_counter) with labels: "name=name1", "event=event2"

Change-Id: Ic9b827d1dbf32a344302d7974457edf9411d2b78
Signed-off-by: Juha Hyttinen <juha.hyttinen@nokia.com>
pkg/xapp/metrics.go
pkg/xapp/metrics_test.go [new file with mode: 0644]

index d2d801c..aa4b0f7 100644 (file)
@@ -26,15 +26,30 @@ import (
        "github.com/prometheus/client_golang/prometheus/promhttp"
 )
 
-type Metrics struct {
-       Namespace string
-}
-
+//-----------------------------------------------------------------------------
 // Alias
+//-----------------------------------------------------------------------------
 type CounterOpts prometheus.Opts
 type Counter prometheus.Counter
 type Gauge prometheus.Gauge
 
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+type MetricGroupsCache struct {
+       Counters map[string]Counter
+       Gauges   map[string]Gauge
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+type Metrics struct {
+       Namespace            string
+       MetricGroupsCacheMap map[string]*MetricGroupsCache
+}
+
 func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
        if url == "" {
                url = "/ric/v1/metrics"
@@ -48,7 +63,7 @@ func NewMetrics(url, namespace string, r *mux.Router) *Metrics {
        // Expose 'metrics' endpoint with standard golang metrics used by prometheus
        r.Handle(url, promhttp.Handler())
 
-       return &Metrics{Namespace: namespace}
+       return &Metrics{Namespace: namespace, MetricGroupsCacheMap: make(map[string]*MetricGroupsCache)}
 }
 
 /*
@@ -129,17 +144,21 @@ func (m *Metrics) RegisterCounterVecGroup(opts []CounterOpts, labelNames []strin
        return
 }
 
-func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
+func (m *Metrics) GetCounterGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
        c = make(map[string]Counter)
        for _, vec := range vects {
                for name, opt := range vec {
-                       c[name] = opt.Vec.WithLabelValues(labels...)
+                       c[prefix+name] = opt.Vec.WithLabelValues(labels...)
                        Logger.Info("Register new counter for vector with opts: %v labels: %v", opt.Opts, labels)
                }
        }
        return
 }
 
+func (m *Metrics) GetCounterGroupFromVects(labels []string, vects ...map[string]CounterVec) (c map[string]Counter) {
+       return m.GetCounterGroupFromVectsWithPrefix("", labels, vects...)
+}
+
 /*
  * Handling gauge vectors
  *
@@ -181,17 +200,22 @@ func (m *Metrics) RegisterGaugeVecGroup(opts []CounterOpts, labelNames []string,
        return
 }
 
-func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
+func (m *Metrics) GetGaugeGroupFromVectsWithPrefix(prefix string, labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
        c = make(map[string]Gauge)
        for _, vec := range vects {
                for name, opt := range vec {
-                       c[name] = opt.Vec.WithLabelValues(labels...)
+                       c[prefix+name] = opt.Vec.WithLabelValues(labels...)
                        Logger.Info("Register new gauge for vector with opts: %v labels: %v", opt.Opts, labels)
                }
        }
        return
 }
 
+func (m *Metrics) GetGaugeGroupFromVects(labels []string, vects ...map[string]GaugeVec) (c map[string]Gauge) {
+       return m.GetGaugeGroupFromVectsWithPrefix("", labels, vects...)
+
+}
+
 /*
  *
  */
@@ -214,3 +238,32 @@ func (m *Metrics) CombineGaugeGroups(srcs ...map[string]Gauge) map[string]Gauge
        }
        return trg
 }
+
+/*
+ *
+ */
+func (m *Metrics) GroupCacheGet(id string) *MetricGroupsCache {
+       entry, ok := m.MetricGroupsCacheMap[id]
+       if ok == false {
+               return nil
+       }
+       return entry
+}
+
+func (m *Metrics) GroupCacheAddCounters(id string, vals map[string]Counter) {
+       entry, ok := m.MetricGroupsCacheMap[id]
+       if ok == false {
+               entry = &MetricGroupsCache{}
+               m.MetricGroupsCacheMap[id] = entry
+       }
+       m.MetricGroupsCacheMap[id].Counters = m.CombineCounterGroups(m.MetricGroupsCacheMap[id].Counters, vals)
+}
+
+func (m *Metrics) GroupCacheAddGauges(id string, vals map[string]Gauge) {
+       entry, ok := m.MetricGroupsCacheMap[id]
+       if ok == false {
+               entry = &MetricGroupsCache{}
+               m.MetricGroupsCacheMap[id] = entry
+       }
+       m.MetricGroupsCacheMap[id].Gauges = m.CombineGaugeGroups(m.MetricGroupsCacheMap[id].Gauges, vals)
+}
diff --git a/pkg/xapp/metrics_test.go b/pkg/xapp/metrics_test.go
new file mode 100644 (file)
index 0000000..ff70ab3
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+==================================================================================
+  Copyright (c) 2019 AT&T Intellectual Property.
+  Copyright (c) 2019 Nokia
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+==================================================================================
+*/
+
+package xapp
+
+import (
+       "testing"
+)
+
+var mCVect map[string]CounterVec
+var mGVect map[string]GaugeVec
+
+func TestMetricSetup(t *testing.T) {
+       mCVect = Metric.RegisterCounterVecGroup(
+               []CounterOpts{
+                       {Name: "counter1", Help: "counter1"},
+               },
+               []string{"name", "event"},
+               "SUBSYSTEM")
+
+       mGVect = Metric.RegisterGaugeVecGroup(
+               []CounterOpts{
+                       {Name: "counter2", Help: "counter2"},
+               },
+               []string{"name", "event"},
+               "SUBSYSTEM")
+}
+
+func TestMetricCounterVector(t *testing.T) {
+       //
+       //
+       c_grp1 := Metric.GetCounterGroupFromVects([]string{"name1", "event1"}, mCVect)
+       if _, ok := c_grp1["counter1"]; ok == false {
+               t.Errorf("c_grp1 counter1 not exists")
+       }
+       c_grp1["counter1"].Inc()
+
+       //
+       //
+       c_grp2 := Metric.GetCounterGroupFromVects([]string{"name1", "event2"}, mCVect)
+       if _, ok := c_grp2["counter1"]; ok == false {
+               t.Errorf("c_grp2 counter1 not exists")
+       }
+       c_grp2["counter1"].Inc()
+}
+
+func TestMetricGaugeVector(t *testing.T) {
+       //
+       //
+       g_grp1 := Metric.GetGaugeGroupFromVects([]string{"name1", "event1"}, mGVect)
+       if _, ok := g_grp1["counter2"]; ok == false {
+               t.Errorf("g_grp1 counter2 not exists")
+       }
+       g_grp1["counter2"].Inc()
+
+       //
+       //
+       g_grp2 := Metric.GetGaugeGroupFromVects([]string{"name1", "event2"}, mGVect)
+       if _, ok := g_grp2["counter2"]; ok == false {
+               t.Errorf("g_grp2 counter2 not exists")
+       }
+       g_grp2["counter2"].Inc()
+}
+
+func TestMetricCounterVectorPrefix(t *testing.T) {
+       //
+       //
+       c_grp1 := Metric.GetCounterGroupFromVectsWithPrefix("event1_", []string{"name1", "event1"}, mCVect)
+       if _, ok := c_grp1["event1_counter1"]; ok == false {
+               t.Errorf("c_grp1 event1_counter1 not exists")
+       }
+       c_grp1["event1_counter1"].Inc()
+
+       //
+       //
+       c_grp2 := Metric.GetCounterGroupFromVectsWithPrefix("event2_", []string{"name1", "event2"}, mCVect)
+       if _, ok := c_grp2["event2_counter1"]; ok == false {
+               t.Errorf("c_grp2 event2_counter1 not exists")
+       }
+       c_grp2["event2_counter1"].Inc()
+
+       //
+       //
+       c_grp := Metric.CombineCounterGroups(c_grp1, c_grp2)
+
+       //
+       //
+       if _, ok := c_grp["event1_counter1"]; ok == false {
+               t.Errorf("c_grp event1_counter1 not exists")
+       }
+       c_grp["event1_counter1"].Inc()
+
+       //
+       //
+       if _, ok := c_grp["event2_counter1"]; ok == false {
+               t.Errorf("c_grp event2_counter1 not exists")
+       }
+       c_grp["event2_counter1"].Inc()
+}
+
+func TestMetricGaugeVectorPrefix(t *testing.T) {
+       //
+       //
+       g_grp1 := Metric.GetGaugeGroupFromVectsWithPrefix("event1_", []string{"name1", "event1"}, mGVect)
+       if _, ok := g_grp1["event1_counter2"]; ok == false {
+               t.Errorf("g_grp1 event1_counter2 not exists")
+       }
+       g_grp1["event1_counter2"].Inc()
+
+       //
+       //
+       g_grp2 := Metric.GetGaugeGroupFromVectsWithPrefix("event2_", []string{"name1", "event2"}, mGVect)
+       if _, ok := g_grp2["event2_counter2"]; ok == false {
+               t.Errorf("g_grp2 event2_counter2 not exists")
+       }
+       g_grp2["event2_counter2"].Inc()
+
+       //
+       //
+       g_grp := Metric.CombineGaugeGroups(g_grp1, g_grp2)
+
+       //
+       //
+       if _, ok := g_grp["event1_counter2"]; ok == false {
+               t.Errorf("g_grp event1_counter2 not exists")
+       }
+       g_grp["event1_counter2"].Inc()
+
+       //
+       //
+       if _, ok := g_grp["event2_counter2"]; ok == false {
+               t.Errorf("g_grp event2_counter2 not exists")
+       }
+       g_grp["event2_counter2"].Inc()
+}
+
+func TestMetricGroupCache(t *testing.T) {
+       //
+       //
+       c_grp1 := Metric.GetCounterGroupFromVectsWithPrefix("event1_", []string{"name1", "event1"}, mCVect)
+       if _, ok := c_grp1["event1_counter1"]; ok == false {
+               t.Errorf("c_grp1 event1_counter1 not exists")
+       }
+       c_grp1["event1_counter1"].Inc()
+
+       //
+       //
+       c_grp2 := Metric.GetCounterGroupFromVectsWithPrefix("event2_", []string{"name1", "event2"}, mCVect)
+       if _, ok := c_grp2["event2_counter1"]; ok == false {
+               t.Errorf("c_grp2 event2_counter1 not exists")
+       }
+       c_grp2["event2_counter1"].Inc()
+
+       //
+       //
+       g_grp1 := Metric.GetGaugeGroupFromVectsWithPrefix("event1_", []string{"name1", "event1"}, mGVect)
+       if _, ok := g_grp1["event1_counter2"]; ok == false {
+               t.Errorf("g_grp1 event1_counter2 not exists")
+       }
+       g_grp1["event1_counter2"].Inc()
+
+       //
+       //
+       g_grp2 := Metric.GetGaugeGroupFromVectsWithPrefix("event2_", []string{"name1", "event2"}, mGVect)
+       if _, ok := g_grp2["event2_counter2"]; ok == false {
+               t.Errorf("g_grp2 event2_counter2 not exists")
+       }
+       g_grp2["event2_counter2"].Inc()
+
+       //
+       //
+       cacheid := "CACHEID"
+       entry := Metric.GroupCacheGet(cacheid)
+       if entry == nil {
+               Metric.GroupCacheAddCounters(cacheid, c_grp1)
+               Metric.GroupCacheAddCounters(cacheid, c_grp2)
+               Metric.GroupCacheAddGauges(cacheid, g_grp1)
+               Metric.GroupCacheAddGauges(cacheid, g_grp2)
+               entry = Metric.GroupCacheGet(cacheid)
+       }
+
+       if entry == nil {
+               t.Errorf("Cache failed")
+       }
+
+       if _, ok := entry.Counters["event1_counter1"]; ok == false {
+               t.Errorf("entry.Counters event1_counter1 not exists")
+       }
+       entry.Counters["event1_counter1"].Inc()
+
+       if _, ok := entry.Counters["event2_counter1"]; ok == false {
+               t.Errorf("entry.Counters event2_counter1 not exists")
+       }
+       entry.Counters["event2_counter1"].Inc()
+
+       if _, ok := entry.Gauges["event1_counter2"]; ok == false {
+               t.Errorf("entry.Gauges event1_counter2 not exists")
+       }
+       entry.Gauges["event1_counter2"].Inc()
+
+       if _, ok := entry.Gauges["event2_counter2"]; ok == false {
+               t.Errorf("entry.Gauges event2_counter2 not exists")
+       }
+       entry.Gauges["event2_counter2"].Inc()
+
+}