From b727e6640f0ae12ce7a2c7f36236055324430370 Mon Sep 17 00:00:00 2001 From: Sean Kim Date: Thu, 9 Jul 2026 15:48:55 -0700 Subject: [PATCH] Parse the native histogram sum as a float _parse_nh_struct parsed the sum field with int(), so a native histogram whose sum is not integral failed to parse with ValueError: invalid literal for int() with base 10: '100.5' NativeHistogram.sum_value is a float and the OpenMetrics writer emits the sum verbatim (e.g. sum:100.5), so the library could not parse its own output for the common case of a non-integer sum. Parse sum with float() to match; count, schema and zero_count remain int as they are genuinely integers. Add test_native_histogram_float_sum, which parses a native histogram with a fractional sum and checks it round-trips to sum_value 100.5. Signed-off-by: Sean Kim --- prometheus_client/openmetrics/parser.py | 2 +- tests/openmetrics/test_parser.py | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/prometheus_client/openmetrics/parser.py b/prometheus_client/openmetrics/parser.py index d967e83b..0c5c9c41 100644 --- a/prometheus_client/openmetrics/parser.py +++ b/prometheus_client/openmetrics/parser.py @@ -315,7 +315,7 @@ def _parse_nh_struct(text): deltas = dict(re_deltas.findall(text)) count_value = int(items['count']) - sum_value = int(items['sum']) + sum_value = float(items['sum']) schema = int(items['schema']) zero_threshold = float(items['zero_threshold']) zero_count = int(items['zero_count']) diff --git a/tests/openmetrics/test_parser.py b/tests/openmetrics/test_parser.py index aeaa6ed6..79a2158c 100644 --- a/tests/openmetrics/test_parser.py +++ b/tests/openmetrics/test_parser.py @@ -218,6 +218,18 @@ def test_native_histogram(self): hfm.add_sample("nativehistogram", None, None, None, None, NativeHistogram(24, 100, 0, 0.001, 4, (BucketSpan(0, 2), BucketSpan(1, 2)), (BucketSpan(0, 2), BucketSpan(1, 2)), (2, 1, -3, 3), (2, 1, -2, 3))) self.assertEqual([hfm], families) + def test_native_histogram_float_sum(self): + families = text_string_to_metric_families("""# TYPE nativehistogram histogram +# HELP nativehistogram Is a basic example of a native histogram +nativehistogram {count:24,sum:100.5,schema:0,zero_threshold:0.001,zero_count:4,positive_spans:[0:2,1:2],negative_spans:[0:2,1:2],positive_deltas:[2,1,-3,3],negative_deltas:[2,1,-2,3]} +# EOF +""") + families = list(families) + + hfm = HistogramMetricFamily("nativehistogram", "Is a basic example of a native histogram") + hfm.add_sample("nativehistogram", None, None, None, None, NativeHistogram(24, 100.5, 0, 0.001, 4, (BucketSpan(0, 2), BucketSpan(1, 2)), (BucketSpan(0, 2), BucketSpan(1, 2)), (2, 1, -3, 3), (2, 1, -2, 3))) + self.assertEqual([hfm], families) + def test_native_histogram_utf8(self): families = text_string_to_metric_families("""# TYPE "native{histogram" histogram # HELP "native{histogram" Is a basic example of a native histogram