Skip to content

Commit cfc67a5

Browse files
authored
Update canonical floats per openmetrics latest. (prometheus#538)
We now only require a specific set of very common le/quantile labels to be in a canonical form. Signed-off-by: Brian Brazil <[email protected]>
1 parent 3be4faf commit cfc67a5

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

prometheus_client/openmetrics/parser.py

+12-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
# Python 3
1616
import io as StringIO
1717

18-
1918
def text_string_to_metric_families(text):
2019
"""Parse Openmetrics text format from a unicode string.
2120
@@ -25,6 +24,16 @@ def text_string_to_metric_families(text):
2524
yield metric_family
2625

2726

27+
_CANONICAL_NUMBERS = set([i / 1000.0 for i in range(10000)] + [10.0**i for i in range(-10, 11)] + [float("inf")])
28+
29+
30+
def _isUncanonicalNumber(s):
31+
f = float(s)
32+
if f not in _CANONICAL_NUMBERS:
33+
return False # Only the canonical numbers are required to be canonical.
34+
return s != floatToGoString(f)
35+
36+
2837
ESCAPE_SEQUENCES = {
2938
'\\\\': '\\',
3039
'\\n': '\n',
@@ -544,11 +553,11 @@ def build_metric(name, documentation, typ, unit, samples):
544553
raise ValueError("Stateset missing label: " + line)
545554
if (typ in ['histogram', 'gaugehistogram'] and name + '_bucket' == sample.name
546555
and (sample.labels.get('le', "NaN") == "NaN"
547-
or sample.labels['le'] != floatToGoString(sample.labels['le']))):
556+
or _isUncanonicalNumber(sample.labels['le']))):
548557
raise ValueError("Invalid le label: " + line)
549558
if (typ == 'summary' and name == sample.name
550559
and (not (0 <= float(sample.labels.get('quantile', -1)) <= 1)
551-
or sample.labels['quantile'] != floatToGoString(sample.labels['quantile']))):
560+
or _isUncanonicalNumber(sample.labels['quantile']))):
552561
raise ValueError("Invalid quantile label: " + line)
553562

554563
g = tuple(sorted(_group_for_sample(sample, name, typ).items()))

tests/openmetrics/test_parser.py

+18-10
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,20 @@ def test_simple_histogram(self):
122122
self.assertEqual([HistogramMetricFamily("a", "help", sum_value=2, buckets=[("1.0", 0.0), ("+Inf", 3.0)])],
123123
list(families))
124124

125+
def test_histogram_noncanonical(self):
126+
families = text_string_to_metric_families("""# TYPE a histogram
127+
# HELP a help
128+
a_bucket{le="0.00000000001"} 0
129+
a_bucket{le="1.1e-4"} 0
130+
a_bucket{le="1.1e-3"} 0
131+
a_bucket{le="100000000000.0"} 0
132+
a_bucket{le="+Inf"} 3
133+
a_count 3
134+
a_sum 2
135+
# EOF
136+
""")
137+
list(families)
138+
125139
def test_negative_bucket_histogram(self):
126140
families = text_string_to_metric_families("""# TYPE a histogram
127141
# HELP a help
@@ -731,9 +745,13 @@ def test_invalid_input(self):
731745
('# TYPE a gaugehistogram\na_gsum 1\n# EOF\n'),
732746
('# TYPE a histogram\na_count 1\na_bucket{le="+Inf"} 0\n# EOF\n'),
733747
('# TYPE a histogram\na_bucket{le="+Inf"} 0\na_count 1\n# EOF\n'),
748+
('# TYPE a histogram\na_bucket{le="0"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
734749
('# TYPE a histogram\na_bucket{le="1"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
750+
('# TYPE a histogram\na_bucket{le="0.0000000001"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
751+
('# TYPE a histogram\na_bucket{le="1.1e-2"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
735752
('# TYPE a histogram\na_bucket{le="1e-04"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
736753
('# TYPE a histogram\na_bucket{le="1e+05"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
754+
('# TYPE a histogram\na_bucket{le="10000000000"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
737755
('# TYPE a histogram\na_bucket{le="+INF"} 0\n# EOF\n'),
738756
('# TYPE a histogram\na_bucket{le="2"} 0\na_bucket{le="1"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
739757
('# TYPE a histogram\na_bucket{le="1"} 1\na_bucket{le="2"} 1\na_bucket{le="+Inf"} 0\n# EOF\n'),
@@ -754,16 +772,6 @@ def test_invalid_input(self):
754772
with self.assertRaises(ValueError, msg=case):
755773
list(text_string_to_metric_families(case))
756774

757-
@unittest.skipIf(sys.version_info < (2, 7), "float repr changed from 2.6 to 2.7")
758-
def test_invalid_float_input(self):
759-
for case in [
760-
# Bad histograms.
761-
('# TYPE a histogram\na_bucket{le="9.999999999999999e+22"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
762-
('# TYPE a histogram\na_bucket{le="1.5555555555555201e+06"} 0\na_bucket{le="+Inf"} 0\n# EOF\n'),
763-
]:
764-
with self.assertRaises(ValueError):
765-
list(text_string_to_metric_families(case))
766-
767775

768776
if __name__ == '__main__':
769777
unittest.main()

0 commit comments

Comments
 (0)