From 364f70401c27768c83822c818cab33da147eb333 Mon Sep 17 00:00:00 2001 From: brecht stamper Date: Thu, 22 Feb 2024 11:06:55 +0100 Subject: [PATCH 1/6] sort by label keys --- .../src/opentelemetry/exporter/prometheus/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py index b1a8d668c4..6cde540ef6 100644 --- a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py +++ b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py @@ -237,7 +237,7 @@ def _translate_to_prometheus( label_keys = [] label_values = [] - for key, value in number_data_point.attributes.items(): + for key, value in sorted(number_data_point.attributes.items()): label_keys.append(self._sanitize(key)) label_values.append(self._check_value(value)) From 729aa229df864cb7b678560d8ea5490a019a7154 Mon Sep 17 00:00:00 2001 From: brecht stamper Date: Fri, 22 Mar 2024 16:03:12 +0100 Subject: [PATCH 2/6] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e983f5ec..4a8ce9b282 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix python 3.12 deprecation warning ([#3751](https://github.com/open-telemetry/opentelemetry-python/pull/3751)) +- Prometheus exporter sort label keys to prevent duplicate metrics when user input changes order ([#3698]https://github.com/open-telemetry/opentelemetry-python/pull/3698) ## Version 1.23.0/0.44b0 (2024-02-23) From 833aceeb5c8d58fa413784a7dc5531e1727ca7cb Mon Sep 17 00:00:00 2001 From: brecht stamper Date: Fri, 22 Mar 2024 16:30:36 +0100 Subject: [PATCH 3/6] test --- .../tests/test_prometheus_exporter.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py index 6d9126c815..da8eeff0d1 100644 --- a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py +++ b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py @@ -436,3 +436,27 @@ def test_target_info_sanitize(self): prometheus_metric.samples[0].labels["ratio"], "0.1", ) + + def test_label_order_does_not_matter(self): + metric_reader = PrometheusMetricReader() + provider = MeterProvider(metric_readers=[metric_reader]) + meter = provider.get_meter("getting-started", "0.1.2") + counter = meter.create_counter("counter") + + counter.add(1, {'cause': 'cause1', 'reason': 'reason1'}) + counter.add(1, {'reason': 'reason2', 'cause': 'cause2'}) + + prometheus_output = generate_latest().decode() + + for line in prometheus_output.split('\n'): + print(line) + + # All labels are mapped correctly + self.assertIn('cause="cause1"', prometheus_output) + self.assertIn('cause="cause2"', prometheus_output) + self.assertIn('reason="reason1"', prometheus_output) + self.assertIn('reason="reason2"', prometheus_output) + + # Only one metric is generated + metric_count = prometheus_output.count('# HELP counter_total') + self.assertEqual(metric_count, 1) From 19916f62d51bc3dac32f0fbeb2914d55589766c9 Mon Sep 17 00:00:00 2001 From: brecht stamper Date: Wed, 17 Apr 2024 12:18:54 +0200 Subject: [PATCH 4/6] review --- CHANGELOG.md | 4 ++-- .../tests/test_prometheus_exporter.py | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51fb31ca29..23077ff4b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#3785](https://github.com/open-telemetry/opentelemetry-python/pull/3785)) - Add capture the fully qualified type name for raised exceptions in spans ([#3837](https://github.com/open-telemetry/opentelemetry-python/pull/3837)) +- Prometheus exporter sort label keys to prevent duplicate metrics when user input changes order + ([#3698](https://github.com/open-telemetry/opentelemetry-python/pull/3698)) ## Version 1.24.0/0.45b0 (2024-03-28) @@ -28,8 +30,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ([#3633](https://github.com/open-telemetry/opentelemetry-python/pull/3633)) - Fix python 3.12 deprecation warning ([#3751](https://github.com/open-telemetry/opentelemetry-python/pull/3751)) -- Prometheus exporter sort label keys to prevent duplicate metrics when user input changes order - ([#3698](https://github.com/open-telemetry/opentelemetry-python/pull/3698)) - bump mypy to 0.982 ([#3776](https://github.com/open-telemetry/opentelemetry-python/pull/3776)) - Add support for OTEL_SDK_DISABLED environment variable diff --git a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py index da8eeff0d1..d39c597782 100644 --- a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py +++ b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py @@ -448,9 +448,6 @@ def test_label_order_does_not_matter(self): prometheus_output = generate_latest().decode() - for line in prometheus_output.split('\n'): - print(line) - # All labels are mapped correctly self.assertIn('cause="cause1"', prometheus_output) self.assertIn('cause="cause2"', prometheus_output) From 9f8046f1d0cc7b16510d9323719870fb10fa0ebc Mon Sep 17 00:00:00 2001 From: brecht stamper Date: Wed, 17 Apr 2024 21:11:00 +0200 Subject: [PATCH 5/6] linting --- .../tests/test_prometheus_exporter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py index d39c597782..7f0cbaaaee 100644 --- a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py +++ b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py @@ -443,8 +443,8 @@ def test_label_order_does_not_matter(self): meter = provider.get_meter("getting-started", "0.1.2") counter = meter.create_counter("counter") - counter.add(1, {'cause': 'cause1', 'reason': 'reason1'}) - counter.add(1, {'reason': 'reason2', 'cause': 'cause2'}) + counter.add(1, {"cause": "cause1", "reason": "reason1"}) + counter.add(1, {"reason": "reason2", "cause": "cause2"}) prometheus_output = generate_latest().decode() @@ -455,5 +455,5 @@ def test_label_order_does_not_matter(self): self.assertIn('reason="reason2"', prometheus_output) # Only one metric is generated - metric_count = prometheus_output.count('# HELP counter_total') + metric_count = prometheus_output.count("# HELP counter_total") self.assertEqual(metric_count, 1) From ef6fd85a42552ceae08c0d677601612c1c91fedc Mon Sep 17 00:00:00 2001 From: Diego Hurtado Date: Wed, 17 Apr 2024 16:54:09 -0500 Subject: [PATCH 6/6] Update contrib SHA --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 651b13ab55..5df83e92ce 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ env: # Otherwise, set variable to the commit of your branch on # opentelemetry-python-contrib which is compatible with these Core repo # changes. - CONTRIB_REPO_SHA: 3c2788469834aa4f5976e1644d757f43d60bc219 + CONTRIB_REPO_SHA: 9ce1c26d2732dfbdadbb492fc38c562dcd08ed2e # This is needed because we do not clone the core repo in contrib builds anymore. # When running contrib builds as part of core builds, we use actions/checkout@v2 which # does not set an environment variable (simply just runs tox), which is different when