From 2d3d36684a0a07d9ba7b5d60c6e979781b0af291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juraj=20Mich=C3=A1lek?= Date: Tue, 13 Feb 2024 23:37:44 +0100 Subject: [PATCH] chore: fix handling of metrics with created suffix (#30808) Description: As discussed in the OTEL Prometheus working group, to fix this case we check If the metricfamily (which we get from the metadata) name + _created == the series name match. Then we treat it as created timestamp. Link to tracking Issue: https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/30309 Testing: Reproduced based on the details provided in the issue, added a test case covering the case. Documentation: --------- Co-authored-by: David Ashpole --- ...ling-of-metrics-with-created-suffix-2.yaml | 27 +++++++++++++++ .../internal/metricfamily.go | 4 +-- .../internal/metricfamily_test.go | 33 +++++++++++++++++-- 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100755 .chloggen/jm-fix-handling-of-metrics-with-created-suffix-2.yaml diff --git a/.chloggen/jm-fix-handling-of-metrics-with-created-suffix-2.yaml b/.chloggen/jm-fix-handling-of-metrics-with-created-suffix-2.yaml new file mode 100755 index 000000000000..1dc9eab5b8b8 --- /dev/null +++ b/.chloggen/jm-fix-handling-of-metrics-with-created-suffix-2.yaml @@ -0,0 +1,27 @@ +# Use this changelog template to create an entry for release notes. + +# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix' +change_type: bug_fix + +# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver) +component: receiver/prometheusreceiver + +# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`). +note: prometheusreceiver fix translation of metrics with _created suffix + +# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists. +issues: [ 30309 ] + +# (Optional) One or more lines of additional information to render under the primary note. +# These lines will be padded with 2 spaces and then inserted directly into the document. +# Use pipe (|) for multiline entries. +subtext: + +# If your change doesn't affect end users or the exported elements of any package, +# you should instead start your pull request title with [chore] or use the "Skip Changelog" label. +# Optional: The change log or logs in which this entry should be included. +# e.g. '[user]' or '[user, api]' +# Include 'user' if the change is relevant to end users. +# Include 'api' if there is a change to a library API. +# Default: '[user]' +change_logs: [] diff --git a/receiver/prometheusreceiver/internal/metricfamily.go b/receiver/prometheusreceiver/internal/metricfamily.go index e501ee5da384..7356fa8f1596 100644 --- a/receiver/prometheusreceiver/internal/metricfamily.go +++ b/receiver/prometheusreceiver/internal/metricfamily.go @@ -287,7 +287,7 @@ func (mf *metricFamily) addSeries(seriesRef uint64, metricName string, ls labels mg.ts = t mg.count = v mg.hasCount = true - case strings.HasSuffix(metricName, metricSuffixCreated): + case metricName == mf.metadata.Metric+metricSuffixCreated: mg.created = v default: boundary, err := getBoundary(mf.mtype, ls) @@ -297,7 +297,7 @@ func (mf *metricFamily) addSeries(seriesRef uint64, metricName string, ls labels mg.complexValue = append(mg.complexValue, &dataPoint{value: v, boundary: boundary}) } case pmetric.MetricTypeSum: - if strings.HasSuffix(metricName, metricSuffixCreated) { + if metricName == mf.metadata.Metric+metricSuffixCreated { mg.created = v } else { mg.value = v diff --git a/receiver/prometheusreceiver/internal/metricfamily_test.go b/receiver/prometheusreceiver/internal/metricfamily_test.go index 10c0f9579480..cb18a813158c 100644 --- a/receiver/prometheusreceiver/internal/metricfamily_test.go +++ b/receiver/prometheusreceiver/internal/metricfamily_test.go @@ -40,6 +40,12 @@ var mc = testMetadataStore{ Help: "This is some help for a counter", Unit: "By", }, + "counter_created": scrape.MetricMetadata{ + Metric: "counter", + Type: textparse.MetricTypeCounter, + Help: "This is some help for a counter", + Unit: "By", + }, "gauge": scrape.MetricMetadata{ Metric: "ge", Type: textparse.MetricTypeGauge, @@ -59,7 +65,7 @@ var mc = testMetadataStore{ Unit: "ms", }, "histogram_with_created": scrape.MetricMetadata{ - Metric: "hg", + Metric: "histogram_with_created", Type: textparse.MetricTypeHistogram, Help: "This is some help for a histogram", Unit: "ms", @@ -77,7 +83,7 @@ var mc = testMetadataStore{ Unit: "ms", }, "summary_with_created": scrape.MetricMetadata{ - Metric: "s", + Metric: "summary_with_created", Type: textparse.MetricTypeSummary, Help: "This is some help for a summary", Unit: "ms", @@ -598,6 +604,29 @@ func TestMetricGroupData_toNumberDataUnitTest(t *testing.T) { {at: 13, value: 33.7, metric: "value"}, {at: 13, value: 150, metric: "value_created"}, }, + want: func() pmetric.NumberDataPoint { + point := pmetric.NewNumberDataPoint() + point.SetDoubleValue(150) + + // the time in milliseconds -> nanoseconds. + point.SetTimestamp(pcommon.Timestamp(13 * time.Millisecond)) + point.SetStartTimestamp(pcommon.Timestamp(13 * time.Millisecond)) + + attributes := point.Attributes() + attributes.PutStr("a", "A") + attributes.PutStr("b", "B") + return point + }, + }, + { + metricKind: "counter_created", + name: "counter:: startTimestampMs from _created", + intervalStartTimestampMs: 11, + labels: labels.FromMap(map[string]string{"a": "A", "b": "B"}), + scrapes: []*scrape{ + {at: 13, value: 33.7, metric: "counter"}, + {at: 13, value: 150, metric: "counter_created"}, + }, want: func() pmetric.NumberDataPoint { point := pmetric.NewNumberDataPoint() point.SetDoubleValue(33.7)