From 0facbff0d009c2e062fbd7acb513a81ef9ce0e88 Mon Sep 17 00:00:00 2001 From: Hiroya Onoe Date: Tue, 30 Jan 2024 00:43:59 +0900 Subject: [PATCH] Prometheus bridge: Add test for verify that start timestamps are working correctly (#4704) Co-authored-by: David Ashpole --- bridges/prometheus/doc.go | 1 - bridges/prometheus/producer_test.go | 86 +++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/bridges/prometheus/doc.go b/bridges/prometheus/doc.go index ea2084ddcf3..abb73f7c6e7 100644 --- a/bridges/prometheus/doc.go +++ b/bridges/prometheus/doc.go @@ -20,7 +20,6 @@ // // Limitations: // - Summary metrics are dropped by the bridge. -// - Start times for histograms and counters are set to the process start time. // - Prometheus histograms are translated to OpenTelemetry fixed-bucket // histograms, rather than exponential histograms. // diff --git a/bridges/prometheus/producer_test.go b/bridges/prometheus/producer_test.go index 41b48806e59..d1f41feb083 100644 --- a/bridges/prometheus/producer_test.go +++ b/bridges/prometheus/producer_test.go @@ -17,6 +17,7 @@ package prometheus // import "go.opentelemetry.io/contrib/bridges/prometheus" import ( "context" "testing" + "time" "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/assert" @@ -251,3 +252,88 @@ func TestProduce(t *testing.T) { }) } } + +func TestProduceForStartTime(t *testing.T) { + testCases := []struct { + name string + testFn func(*prometheus.Registry) + startTimeFn func(metricdata.Aggregation) []time.Time + }{ + { + name: "counter", + testFn: func(reg *prometheus.Registry) { + metric := prometheus.NewCounter(prometheus.CounterOpts{ + Name: "test_counter_metric", + Help: "A counter metric for testing", + ConstLabels: prometheus.Labels(map[string]string{ + "foo": "bar", + }), + }) + reg.MustRegister(metric) + metric.(prometheus.ExemplarAdder).AddWithExemplar( + 245.3, prometheus.Labels{ + "trace_id": traceIDStr, + "span_id": spanIDStr, + "other_attribute": "abcd", + }, + ) + }, + startTimeFn: func(aggr metricdata.Aggregation) []time.Time { + dps := aggr.(metricdata.Sum[float64]).DataPoints + sts := make([]time.Time, len(dps)) + for i, dp := range dps { + sts[i] = dp.StartTime + } + return sts + }, + }, + { + name: "histogram", + testFn: func(reg *prometheus.Registry) { + metric := prometheus.NewHistogram(prometheus.HistogramOpts{ + Name: "test_histogram_metric", + Help: "A histogram metric for testing", + ConstLabels: prometheus.Labels(map[string]string{ + "foo": "bar", + }), + }) + reg.MustRegister(metric) + metric.(prometheus.ExemplarObserver).ObserveWithExemplar( + 578.3, prometheus.Labels{ + "trace_id": traceIDStr, + "span_id": spanIDStr, + "other_attribute": "efgh", + }, + ) + }, + startTimeFn: func(aggr metricdata.Aggregation) []time.Time { + dps := aggr.(metricdata.Histogram[float64]).DataPoints + sts := make([]time.Time, len(dps)) + for i, dp := range dps { + sts[i] = dp.StartTime + } + return sts + }, + }, + } + for _, tt := range testCases { + t.Run(tt.name, func(t *testing.T) { + reg := prometheus.NewRegistry() + tt.testFn(reg) + p := NewMetricProducer(WithGatherer(reg)) + output, err := p.Produce(context.Background()) + assert.NoError(t, err) + assert.NotEmpty(t, output) + for _, sms := range output { + assert.NotEmpty(t, sms.Metrics) + for _, ms := range sms.Metrics { + sts := tt.startTimeFn(ms.Data) + assert.NotEmpty(t, sts) + for _, st := range sts { + assert.True(t, st.After(processStartTime)) + } + } + } + }) + } +}