Skip to content

Commit

Permalink
Refactor metrics library and complete implementation (#24)
Browse files Browse the repository at this point in the history
* refactor metrics library

Signed-off-by: Jayadeep KM <[email protected]>

* add vendor, fix go.sum

Signed-off-by: Jayadeep KM <[email protected]>

* add test cases, add help test

Signed-off-by: Jayadeep KM <[email protected]>

---------

Signed-off-by: Jayadeep KM <[email protected]>
  • Loading branch information
kmjayadeep authored Apr 4, 2023
1 parent 212c13d commit 9338c8e
Show file tree
Hide file tree
Showing 1,917 changed files with 888,574 additions and 232 deletions.
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/go-logr/zapr v1.2.3
github.com/kubeslice/apis v0.1.2
github.com/prometheus/client_golang v1.14.0
github.com/stretchr/testify v1.8.0
github.com/prometheus/client_model v0.3.0
go.uber.org/zap v1.24.0
golang.org/x/net v0.5.0
gopkg.in/yaml.v2 v2.4.0
Expand All @@ -32,8 +32,6 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
Expand Down
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -444,16 +444,13 @@ github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
Expand Down
198 changes: 61 additions & 137 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -1,159 +1,83 @@
package metrics

import (
"context"
"github.com/kubeslice/kubeslice-monitoring/pkg/util"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
"time"
"github.com/prometheus/client_golang/prometheus/promauto"
)

// MetricRecorder provides a container with config parameters for the Prometheus Exporter
type MetricRecorder struct {
Logger *zap.SugaredLogger
Project string
Cluster string
Slice string
Namespace string
Subsystem string
// MetricRecorder is used to record metrics from a component
type MetricsFactory interface {
NewCounter(string, string, []string) *prometheus.CounterVec
NewGauge(string, string, []string) *prometheus.GaugeVec
NewHistogram(string, string, []string) prometheus.ObserverVec
}

type Metric struct {
Type MetricType
Name string
Help string
Value float64
Labels map[string]string
HistogramBuckets []float64
Time time.Time
type MetricsFactoryOptions struct {
Project string
Slice string
Cluster string
Namespace string
ReportingController string
}

type MetricType string

var fixedLabels = []string{"slice_project", "slice_cluster", "slice_name"}

const (
MetricTypeGauge = "Gauge"
MetricTypeCounter = "Counter"
MetricTypeHistogram = "Histogram"
MetricTypeSummary = "Summary"
)

// Copy returns a Provider that produces Prometheus metrics.
// Namespace and subsystem are applied to all produced metrics.
func (mr *MetricRecorder) Copy() *MetricRecorder {
return &MetricRecorder{
Logger: mr.Logger,
Project: mr.Project,
Cluster: mr.Cluster,
Slice: mr.Slice,
Namespace: mr.Namespace,
Subsystem: mr.Subsystem,
}
type metricsFactory struct {
Registerer prometheus.Registerer
Options MetricsFactoryOptions
}

// RecordMetric records a metric to the Prometheus Exporter
func (mr *MetricRecorder) RecordMetric(ctx context.Context, m *Metric) error {
switch m.Type {
case MetricTypeGauge:
mr.recordGauge(ctx, m)
break
case MetricTypeCounter:
mr.recordCounter(ctx, m)
break
case MetricTypeHistogram:
mr.recordHistogram(ctx, m)
break
case MetricTypeSummary:
mr.recordSummary(ctx, m)
break
default:
mr.Logger.Errorf("Unknown metric type: %v", m.Type)
func NewMetricsFactory(r prometheus.Registerer, o MetricsFactoryOptions) (MetricsFactory, error) {
mf := &metricsFactory{
Registerer: r,
Options: o,
}
return nil
return mf, nil
}

func (mr *MetricRecorder) recordGauge(ctx context.Context, m *Metric) {
mr.Logger.Debugf("Recording gauge metric: %v", m)
metric := prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Namespace: util.FlattenString(mr.Namespace),
Subsystem: util.FlattenString(mr.Subsystem),
Name: util.FlattenString(m.Name),
Help: m.Help,
},
append(fixedLabels, util.KeysFromMap(m.Labels)...),
)
metric.With(
util.MergeMaps(
prometheus.Labels{
"slice_project": util.FlattenString(mr.Project),
"slice_cluster": util.FlattenString(mr.Cluster),
"slice_name": util.FlattenString(mr.Slice),
}, util.FlattenMap(m.Labels)),
).Set(m.Value)
// Adds slice labels to the list of labels provided
// Returns the new set of labels and slice labels
func (m *metricsFactory) getCurryLabels(labels []string) ([]string, prometheus.Labels) {
pl := prometheus.Labels{
"slice_name": m.Options.Slice,
"slice_project": m.Options.Project,
"slice_cluster": m.Options.Cluster,
"slice_namespace": m.Options.Namespace,
"slice_reporting_controller": m.Options.ReportingController,
}
for k, v := range pl {
// Remove labels if value is empty
if v == "" {
delete(pl, k)
continue
}
// add the new label to original list of labels provided
labels = append(labels, k)
}
return labels, pl
}

func (mr *MetricRecorder) recordCounter(ctx context.Context, m *Metric) {
mr.Logger.Debugf("Recording counter metric: %v", m)
metric := prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: util.FlattenString(mr.Namespace),
Subsystem: util.FlattenString(mr.Subsystem),
Name: util.FlattenString(m.Name),
Help: m.Help,
},
append(fixedLabels, util.KeysFromMap(m.Labels)...),
)
metric.With(
util.MergeMaps(
prometheus.Labels{
"slice_project": util.FlattenString(mr.Project),
"slice_cluster": util.FlattenString(mr.Cluster),
"slice_name": util.FlattenString(mr.Slice),
}, util.FlattenMap(m.Labels)),
).Add(m.Value)
func (m *metricsFactory) NewCounter(name string, help string, labels []string) *prometheus.CounterVec {
labels, cl := m.getCurryLabels(labels)
return promauto.With(m.Registerer).NewCounterVec(prometheus.CounterOpts{
Namespace: "kubeslice",
Name: name,
Help: help,
}, labels).MustCurryWith(cl)
}

func (mr *MetricRecorder) recordHistogram(ctx context.Context, m *Metric) {
mr.Logger.Debugf("Recording histogram metric: %v", m)
metric := prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: util.FlattenString(mr.Namespace),
Subsystem: util.FlattenString(mr.Subsystem),
Name: util.FlattenString(m.Name),
Help: m.Help,
Buckets: m.HistogramBuckets,
},
append(fixedLabels, util.KeysFromMap(m.Labels)...),
)
metric.With(
util.MergeMaps(
prometheus.Labels{
"slice_project": util.FlattenString(mr.Project),
"slice_cluster": util.FlattenString(mr.Cluster),
"slice_name": util.FlattenString(mr.Slice),
}, util.FlattenMap(m.Labels)),
).Observe(time.Since(m.Time).Seconds())
func (m *metricsFactory) NewGauge(name string, help string, labels []string) *prometheus.GaugeVec {
labels, cl := m.getCurryLabels(labels)
return promauto.With(m.Registerer).NewGaugeVec(prometheus.GaugeOpts{
Namespace: "kubeslice",
Name: name,
Help: help,
}, labels).MustCurryWith(cl)
}

func (mr *MetricRecorder) recordSummary(ctx context.Context, m *Metric) {
mr.Logger.Debugf("Recording summary metric: %v", m)
metric := prometheus.NewSummaryVec(
prometheus.SummaryOpts{
Namespace: util.FlattenString(mr.Namespace),
Subsystem: util.FlattenString(mr.Subsystem),
Name: util.FlattenString(m.Name),
Help: m.Help,
},
append(fixedLabels, util.KeysFromMap(m.Labels)...),
)
metric.With(
util.MergeMaps(
prometheus.Labels{
"slice_project": util.FlattenString(mr.Project),
"slice_cluster": util.FlattenString(mr.Cluster),
"slice_name": util.FlattenString(mr.Slice),
}, util.FlattenMap(m.Labels)),
).Observe(time.Since(m.Time).Seconds())
func (m *metricsFactory) NewHistogram(name string, help string, labels []string) prometheus.ObserverVec {
labels, cl := m.getCurryLabels(labels)
return promauto.With(m.Registerer).NewHistogramVec(prometheus.HistogramOpts{
Namespace: "kubeslice",
Name: name,
Help: help,
}, labels).MustCurryWith(cl)
}
Loading

0 comments on commit 9338c8e

Please sign in to comment.