From 87fd8efb56ffe9640bb386b474956d3adbe76f93 Mon Sep 17 00:00:00 2001 From: gunli Date: Mon, 3 Apr 2023 10:23:26 +0800 Subject: [PATCH] Add const labels to isolate metrics --- prometheusmetrics.go | 15 ++++--- prometheusmetrics_test.go | 92 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/prometheusmetrics.go b/prometheusmetrics.go index 4086c01..a32b4ee 100644 --- a/prometheusmetrics.go +++ b/prometheusmetrics.go @@ -24,11 +24,12 @@ type PrometheusConfig struct { histogramBuckets []float64 timerBuckets []float64 mutex *sync.Mutex + constLabels map[string]string } // NewPrometheusProvider returns a Provider that produces Prometheus metrics. // Namespace and subsystem are applied to all produced metrics. -func NewPrometheusProvider(r metrics.Registry, namespace string, subsystem string, promRegistry prometheus.Registerer, FlushInterval time.Duration) *PrometheusConfig { +func NewPrometheusProvider(r metrics.Registry, namespace string, subsystem string, promRegistry prometheus.Registerer, FlushInterval time.Duration, constLabels map[string]string) *PrometheusConfig { return &PrometheusConfig{ namespace: namespace, subsystem: subsystem, @@ -40,6 +41,7 @@ func NewPrometheusProvider(r metrics.Registry, namespace string, subsystem strin histogramBuckets: []float64{0.05, 0.1, 0.25, 0.50, 0.75, 0.9, 0.95, 0.99}, timerBuckets: []float64{0.50, 0.95, 0.99, 0.999}, mutex: new(sync.Mutex), + constLabels: constLabels, } } @@ -71,10 +73,11 @@ func (c *PrometheusConfig) gaugeFromNameAndValue(name string, val float64) { g, ok := c.gauges[key] if !ok { g = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: c.flattenKey(c.namespace), - Subsystem: c.flattenKey(c.subsystem), - Name: c.flattenKey(name), - Help: name, + Namespace: c.flattenKey(c.namespace), + Subsystem: c.flattenKey(c.subsystem), + Name: c.flattenKey(name), + Help: name, + ConstLabels: c.constLabels, }) c.promRegistry.Register(g) c.gauges[key] = g @@ -127,7 +130,7 @@ func (c *PrometheusConfig) histogramFromNameAndMetric(name string, goMetric inte ), c.flattenKey(name), []string{}, - map[string]string{}, + c.constLabels, ) if constHistogram, err := prometheus.NewConstHistogram( diff --git a/prometheusmetrics_test.go b/prometheusmetrics_test.go index 6238172..dfdc66c 100644 --- a/prometheusmetrics_test.go +++ b/prometheusmetrics_test.go @@ -12,7 +12,7 @@ import ( func TestPrometheusRegistration(t *testing.T) { defaultRegistry := prometheus.DefaultRegisterer - pClient := NewPrometheusProvider(metrics.DefaultRegistry, "test", "subsys", defaultRegistry, 1*time.Second) + pClient := NewPrometheusProvider(metrics.DefaultRegistry, "test", "subsys", defaultRegistry, 1*time.Second, nil) if pClient.promRegistry != defaultRegistry { t.Fatalf("Failed to pass prometheus registry to go-metrics provider") } @@ -21,7 +21,7 @@ func TestPrometheusRegistration(t *testing.T) { func TestUpdatePrometheusMetricsOnce(t *testing.T) { prometheusRegistry := prometheus.NewRegistry() metricsRegistry := metrics.NewRegistry() - pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second) + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, nil) metricsRegistry.Register("counter", metrics.NewCounter()) pClient.UpdatePrometheusMetricsOnce() gauge := prometheus.NewGauge(prometheus.GaugeOpts{ @@ -40,7 +40,7 @@ func TestUpdatePrometheusMetricsOnce(t *testing.T) { func TestUpdatePrometheusMetrics(t *testing.T) { prometheusRegistry := prometheus.NewRegistry() metricsRegistry := metrics.NewRegistry() - pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second) + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, nil) metricsRegistry.Register("counter", metrics.NewCounter()) go pClient.UpdatePrometheusMetrics() time.Sleep(2 * time.Second) @@ -60,7 +60,7 @@ func TestUpdatePrometheusMetrics(t *testing.T) { func TestPrometheusCounterGetUpdated(t *testing.T) { prometheusRegistry := prometheus.NewRegistry() metricsRegistry := metrics.NewRegistry() - pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second) + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, nil) cntr := metrics.NewCounter() metricsRegistry.Register("counter", cntr) cntr.Inc(2) @@ -75,10 +75,30 @@ func TestPrometheusCounterGetUpdated(t *testing.T) { } } +func TestPrometheusCounterGetUpdatedWithLabels(t *testing.T) { + prometheusRegistry := prometheus.NewRegistry() + metricsRegistry := metrics.NewRegistry() + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, map[string]string{"name": "value"}) + cntr := metrics.NewCounter() + metricsRegistry.Register("counter", cntr) + cntr.Inc(2) + go pClient.UpdatePrometheusMetrics() + cntr.Inc(13) + time.Sleep(5 * time.Second) + metrics, _ := prometheusRegistry.Gather() + serialized := fmt.Sprint(metrics[0]) + expected := fmt.Sprintf("name:\"test_subsys_counter\" help:\"counter\" type:GAUGE metric: gauge: > ", cntr.Count()) + if serialized != expected { + fmt.Println(serialized) + fmt.Println(expected) + t.Fatalf("Go-metrics value and prometheus metrics value do not match") + } +} + func TestPrometheusGaugeGetUpdated(t *testing.T) { prometheusRegistry := prometheus.NewRegistry() metricsRegistry := metrics.NewRegistry() - pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second) + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, nil) gm := metrics.NewGauge() metricsRegistry.Register("gauge", gm) gm.Update(2) @@ -96,10 +116,31 @@ func TestPrometheusGaugeGetUpdated(t *testing.T) { } } +func TestPrometheusGaugeGetUpdatedWithLabels(t *testing.T) { + prometheusRegistry := prometheus.NewRegistry() + metricsRegistry := metrics.NewRegistry() + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, map[string]string{"name": "value"}) + gm := metrics.NewGauge() + metricsRegistry.Register("gauge", gm) + gm.Update(2) + go pClient.UpdatePrometheusMetrics() + gm.Update(13) + time.Sleep(5 * time.Second) + metrics, _ := prometheusRegistry.Gather() + if len(metrics) == 0 { + t.Fatalf("prometheus was unable to register the metric") + } + serialized := fmt.Sprint(metrics[0]) + expected := fmt.Sprintf("name:\"test_subsys_gauge\" help:\"gauge\" type:GAUGE metric: gauge: > ", gm.Value()) + if serialized != expected { + t.Fatalf("Go-metrics value and prometheus metrics value do not match") + } +} + func TestPrometheusMeterGetUpdated(t *testing.T) { prometheusRegistry := prometheus.NewRegistry() metricsRegistry := metrics.NewRegistry() - pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second) + pClient := NewPrometheusProvider(metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, nil) gm := metrics.NewMeter() metricsRegistry.Register("meter", gm) gm.Mark(2) @@ -140,6 +181,7 @@ func TestPrometheusHistogramGetUpdated(t *testing.T) { pClient := NewPrometheusProvider( metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, + nil, ) // values := make([]int64, 0) //sample := metrics.HistogramSnapshot{metrics.NewSampleSnapshot(int64(len(values)), values)} @@ -170,12 +212,50 @@ func TestPrometheusHistogramGetUpdated(t *testing.T) { } } +func TestPrometheusHistogramGetUpdatedWithLabels(t *testing.T) { + prometheusRegistry := prometheus.NewRegistry() + metricsRegistry := metrics.NewRegistry() + pClient := NewPrometheusProvider( + metricsRegistry, "test", "subsys", + prometheusRegistry, 1*time.Second, + map[string]string{"name": "value"}, + ) + // values := make([]int64, 0) + //sample := metrics.HistogramSnapshot{metrics.NewSampleSnapshot(int64(len(values)), values)} + gm := metrics.NewHistogram(metrics.NewUniformSample(1028)) + metricsRegistry.Register("metric", gm) + + for ii := 0; ii < 94; ii++ { + gm.Update(1) + } + for ii := 0; ii < 5; ii++ { + gm.Update(5) + } + gm.Update(10) + + go pClient.UpdatePrometheusMetrics() + time.Sleep(5 * time.Second) + metrics, _ := prometheusRegistry.Gather() + + if len(metrics) < 2 { + t.Fatalf("prometheus was unable to register the metric") + } + + serialized := fmt.Sprint(metrics[1]) + + expected := `name:"test_subsys_metric_histogram" help:"metric" type:HISTOGRAM metric: histogram: bucket: bucket: bucket: bucket: bucket: bucket: bucket: > > ` + if serialized != expected { + t.Fatalf("Go-metrics value and prometheus metrics value for max do not match:\n+ %s\n- %s", serialized, expected) + } +} + func TestPrometheusTimerGetUpdated(t *testing.T) { prometheusRegistry := prometheus.NewRegistry() metricsRegistry := metrics.NewRegistry() pClient := NewPrometheusProvider( metricsRegistry, "test", "subsys", prometheusRegistry, 1*time.Second, + nil, ) timer := metrics.NewTimer() metricsRegistry.Register("timer", timer)