From fce28cacd72f1ed74817d47a3eba8ae9ad1876e1 Mon Sep 17 00:00:00 2001 From: emdneto <9735060+emdneto@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:17:20 -0300 Subject: [PATCH 1/4] show tests fail at CI without the change Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com> --- .../exporter/prometheus/__init__.py | 14 ++--- .../tests/test_prometheus_exporter.py | 56 +++++++++++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) 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 e0f7360e35..f507405d8d 100644 --- a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py +++ b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py @@ -224,15 +224,14 @@ def _translate_to_prometheus( metrics.append(metric) for metric in metrics: - label_valuess = [] + label_values_data_points = [] + label_keys_data_points = [] values = [] - pre_metric_family_ids = [] + per_metric_family_ids = [] metric_name = sanitize_full_name(metric.name) - metric_description = metric.description or "" - metric_unit = map_unit(metric.unit) for number_data_point in metric.data.data_points: @@ -243,7 +242,7 @@ def _translate_to_prometheus( label_keys.append(sanitize_attribute(key)) label_values.append(self._check_value(value)) - pre_metric_family_ids.append( + per_metric_family_ids.append( "|".join( [ metric_name, @@ -254,7 +253,8 @@ def _translate_to_prometheus( ) ) - label_valuess.append(label_values) + label_values_data_points.append(label_values) + label_keys_data_points.append(label_keys) if isinstance(number_data_point, HistogramDataPoint): values.append( { @@ -269,7 +269,7 @@ def _translate_to_prometheus( values.append(number_data_point.value) for pre_metric_family_id, label_values, value in zip( - pre_metric_family_ids, label_valuess, values + per_metric_family_ids, label_values_data_points, values ): is_non_monotonic_sum = ( isinstance(metric.data, Sum) diff --git a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py index 623a16927b..a7a3868a8a 100644 --- a/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py +++ b/exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py @@ -638,3 +638,59 @@ def test_semconv(self): """ ), ) + + def test_multiple_data_points_with_different_label_sets(self): + hist_point_1 = HistogramDataPoint( + attributes={"http_target": "/foobar", "net_host_port": 8080}, + start_time_unix_nano=1641946016139533244, + time_unix_nano=1641946016139533244, + count=6, + sum=579.0, + bucket_counts=[1, 3, 2], + explicit_bounds=[123.0, 456.0], + min=1, + max=457, + ) + hist_point_2 = HistogramDataPoint( + attributes={"net_host_port": 8080}, + start_time_unix_nano=1641946016139533245, + time_unix_nano=1641946016139533245, + count=7, + sum=579.0, + bucket_counts=[1, 3, 3], + explicit_bounds=[123.0, 456.0], + min=1, + max=457, + ) + + metric = Metric( + name="http.server.request.duration", + description="test multiple label sets", + unit="s", + data=Histogram( + data_points=[hist_point_1, hist_point_2], + aggregation_temporality=AggregationTemporality.CUMULATIVE, + ), + ) + + self.verify_text_format( + metric, + dedent( + """\ + # HELP http_server_request_duration_seconds test multiple label sets + # TYPE http_server_request_duration_seconds histogram + http_server_request_duration_seconds_bucket{http_target="/foobar",le="123.0",net_host_port="8080"} 1.0 + http_server_request_duration_seconds_bucket{http_target="/foobar",le="456.0",net_host_port="8080"} 4.0 + http_server_request_duration_seconds_bucket{http_target="/foobar",le="+Inf",net_host_port="8080"} 6.0 + http_server_request_duration_seconds_count{http_target="/foobar",net_host_port="8080"} 6.0 + http_server_request_duration_seconds_sum{http_target="/foobar",net_host_port="8080"} 579.0 + # HELP http_server_request_duration_seconds test multiple label sets + # TYPE http_server_request_duration_seconds histogram + http_server_request_duration_seconds_bucket{le="123.0",net_host_port="8080"} 1.0 + http_server_request_duration_seconds_bucket{le="456.0",net_host_port="8080"} 4.0 + http_server_request_duration_seconds_bucket{le="+Inf",net_host_port="8080"} 7.0 + http_server_request_duration_seconds_count{net_host_port="8080"} 7.0 + http_server_request_duration_seconds_sum{net_host_port="8080"} 579.0 + """ + ), + ) From 2c1ba93699c9f91e09905cfaaf610b8947e8c797 Mon Sep 17 00:00:00 2001 From: emdneto <9735060+emdneto@users.noreply.github.com> Date: Tue, 4 Feb 2025 18:28:30 -0300 Subject: [PATCH 2/4] now it should work Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com> --- .../src/opentelemetry/exporter/prometheus/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 f507405d8d..572dd29c59 100644 --- a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py +++ b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py @@ -268,8 +268,11 @@ def _translate_to_prometheus( else: values.append(number_data_point.value) - for pre_metric_family_id, label_values, value in zip( - per_metric_family_ids, label_values_data_points, values + for pre_metric_family_id, label_keys, label_values, value in zip( + per_metric_family_ids, + label_keys_data_points, + label_values_data_points, + values, ): is_non_monotonic_sum = ( isinstance(metric.data, Sum) From 15029843f158ad08cbb0430ea4d5ca4747704168 Mon Sep 17 00:00:00 2001 From: emdneto <9735060+emdneto@users.noreply.github.com> Date: Tue, 4 Feb 2025 19:01:16 -0300 Subject: [PATCH 3/4] refactor variables Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com> --- .../src/opentelemetry/exporter/prometheus/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 572dd29c59..475cfb1266 100644 --- a/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py +++ b/exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py @@ -268,7 +268,7 @@ def _translate_to_prometheus( else: values.append(number_data_point.value) - for pre_metric_family_id, label_keys, label_values, value in zip( + for per_metric_family_id, label_keys, label_values, value in zip( per_metric_family_ids, label_keys_data_points, label_values_data_points, @@ -294,7 +294,7 @@ def _translate_to_prometheus( and not should_convert_sum_to_gauge ): metric_family_id = "|".join( - [pre_metric_family_id, CounterMetricFamily.__name__] + [per_metric_family_id, CounterMetricFamily.__name__] ) if metric_family_id not in metric_family_id_metric_family: @@ -314,7 +314,7 @@ def _translate_to_prometheus( or should_convert_sum_to_gauge ): metric_family_id = "|".join( - [pre_metric_family_id, GaugeMetricFamily.__name__] + [per_metric_family_id, GaugeMetricFamily.__name__] ) if ( @@ -334,7 +334,7 @@ def _translate_to_prometheus( ].add_metric(labels=label_values, value=value) elif isinstance(metric.data, Histogram): metric_family_id = "|".join( - [pre_metric_family_id, HistogramMetricFamily.__name__] + [per_metric_family_id, HistogramMetricFamily.__name__] ) if ( From a50e0d1648703532226a3fcd80a346da28a1a30e Mon Sep 17 00:00:00 2001 From: emdneto <9735060+emdneto@users.noreply.github.com> Date: Tue, 4 Feb 2025 19:03:30 -0300 Subject: [PATCH 4/4] add changelog Signed-off-by: emdneto <9735060+emdneto@users.noreply.github.com> --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbcb6634df..f7c7f2dce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- prometheus-exporter: fix labels out of place for data points with different + attribute sets + ([#4413](https://github.com/open-telemetry/opentelemetry-python/pull/4413)) + ## Version 1.30.0/0.51b0 (2025-02-03) - Always setup logs sdk, OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED only controls python `logging` module handler setup