From e29ed9f2cda2e35829a5ee139e0a283ba521c153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vila=C3=A7a?= Date: Thu, 15 Dec 2022 15:07:45 +0000 Subject: [PATCH] Support for multiple samples within same metric (#1181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: João Vilaça Signed-off-by: João Vilaça --- prometheus/registry.go | 5 +++++ prometheus/registry_test.go | 45 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/prometheus/registry.go b/prometheus/registry.go index f5afeb074..dac557958 100644 --- a/prometheus/registry.go +++ b/prometheus/registry.go @@ -21,6 +21,7 @@ import ( "path/filepath" "runtime" "sort" + "strconv" "strings" "sync" "unicode/utf8" @@ -933,6 +934,10 @@ func checkMetricConsistency( h.WriteString(lp.GetValue()) h.Write(separatorByteSlice) } + if dtoMetric.TimestampMs != nil { + h.WriteString(strconv.FormatInt(*(dtoMetric.TimestampMs), 10)) + h.Write(separatorByteSlice) + } hSum := h.Sum64() if _, exists := metricHashes[hSum]; exists { return fmt.Errorf( diff --git a/prometheus/registry_test.go b/prometheus/registry_test.go index 3faf67aa5..73b49fb9b 100644 --- a/prometheus/registry_test.go +++ b/prometheus/registry_test.go @@ -1288,3 +1288,48 @@ func ExampleRegistry_grouping() { }(i) } } + +type customCollector struct { + collectFunc func(ch chan<- prometheus.Metric) +} + +func (co *customCollector) Describe(_ chan<- *prometheus.Desc) {} + +func (co *customCollector) Collect(ch chan<- prometheus.Metric) { + co.collectFunc(ch) +} + +// TestCheckMetricConsistency +func TestCheckMetricConsistency(t *testing.T) { + reg := prometheus.NewRegistry() + timestamp := time.Now() + + desc := prometheus.NewDesc("metric_a", "", nil, nil) + metric := prometheus.MustNewConstMetric(desc, prometheus.CounterValue, 1) + + validCollector := &customCollector{ + collectFunc: func(ch chan<- prometheus.Metric) { + ch <- prometheus.NewMetricWithTimestamp(timestamp.Add(-1*time.Minute), metric) + ch <- prometheus.NewMetricWithTimestamp(timestamp, metric) + }, + } + reg.MustRegister(validCollector) + _, err := reg.Gather() + if err != nil { + t.Error("metric validation should succeed:", err) + } + reg.Unregister(validCollector) + + invalidCollector := &customCollector{ + collectFunc: func(ch chan<- prometheus.Metric) { + ch <- prometheus.NewMetricWithTimestamp(timestamp, metric) + ch <- prometheus.NewMetricWithTimestamp(timestamp, metric) + }, + } + reg.MustRegister(invalidCollector) + _, err = reg.Gather() + if err == nil { + t.Error("metric validation should return an error") + } + reg.Unregister(invalidCollector) +}