10000 Add support for exemplars on counters. (#434) · lweith/client_python@4712878 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4712878

Browse files
authored
Add support for exemplars on counters. (prometheus#434)
Signed-off-by: Brian Brazil <brian.brazil@robustperception.io>
1 parent 6b091ab commit 4712878

File tree

2 files changed

+21
-9
lines changed

2 files changed

+21
-9
lines changed

prometheus_client/openmetrics/parser.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,11 @@ def _parse_labels(text):
238238

239239

240240
def _parse_sample(text):
241+
seperator = " # "
241242
# Detect the labels in the text
242243
label_start = text.find("{")
243-
if label_start == -1:
244-
# We don't have labels
244+
if label_start == -1 or seperator in text[:label_start]:
245+
# We don't have labels, but there could be an exemplar.
245246
name_end = text.index(" ")
246247
name = text[:name_end]
247248
# Parse the remaining text after the name
@@ -250,8 +251,7 @@ def _parse_sample(text):
250251
return Sample(name, {}, value, timestamp, exemplar)
251252
# The name is before the labels
252253
name = text[:label_start]
253-
seperator = " # "
254-
if text.count(seperator) == 0:
254+
if seperator not in text:
255255
# Line doesn't contain an exemplar
256256
# We can use `rindex` to find `label_end`
257257
label_end = text.rindex("}")
@@ -261,7 +261,7 @@ def _parse_sample(text):
261261
# Line potentially contains an exemplar
262262
# Fallback to parsing labels with a state machine
263263
labels, labels_len = _parse_labels_with_state_machine(text[label_start + 1:])
264-
label_end = labels_len + len(name)
264+
label_end = labels_len + len(name)
265265
# Parsing labels succeeded, continue parsing the remaining text
266266
remaining_text = text[label_end + 2:]
267267
value, timestamp, exemplar = _parse_remaining_text(remaining_text)
@@ -564,9 +564,9 @@ def build_metric(name, documentation, typ, unit, samples):
564564
'_gsum'] and sample.value < 0:
565565
raise ValueError("Counter-like samples cannot be negative: " + line)
566566
if sample.exemplar and not (
567-
typ in ['histogram', 'gaugehistogram']
568-
and sample.name.endswith('_bucket')):
569-
raise ValueError("Invalid line only histogram/gaugehistogram buckets can have exemplars: " + line)
567+
(typ in ['histogram', 'gaugehistogram'] and sample.name.endswith('_bucket'))
568+
or (typ in ['counter'] and sample.name.endswith('_total'))):
569+
raise ValueError("Invalid line only histogram/gaugehistogram buckets and counters can have exemplars: " + line)
570570

571571
if name is not None:
572572
yield build_metric(name, documentation, typ, unit, samples)

tests/openmetrics/test_parser.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ def test_gaugehistogram_exemplars(self):
148148
hfm.add_sample("a_bucket", {"le": "+Inf"}, 3.0, Timestamp(123, 0), Exemplar({"a": "d"}, 4, Timestamp(123, 0)))
149149
self.assertEqual([hfm], list(families))
150150

151+
def test_counter_exemplars(self):
152+
families = text_string_to_metric_families("""# TYPE a counter
153+
# HELP a help
154+
a_total 0 123 # {a="b"} 0.5
155+
# EOF
156+
""")
157+
cfm = CounterMetricFamily("a", "help")
158+
cfm.add_sample("a_total", {}, 0.0, Timestamp(123, 0), Exemplar({"a": "b"}, 0.5))
159+
self.assertEqual([cfm], list(families))
160+
151161
def test_simple_info(self):
152162
families = text_string_to_metric_families("""# TYPE a info
153163
# HELP a help
@@ -616,9 +626,11 @@ def test_invalid_input(self):
616626
('# TYPE a histogram\na_sum 1 # {a="b"} 0.5\n# EOF\n'),
617627
('# TYPE a gaugehistogram\na_sum 1 # {a="b"} 0.5\n# EOF\n'),
618628
('# TYPE a_bucket gauge\na_bucket 1 # {a="b"} 0.5\n# EOF\n'),
629+
('# TYPE a counter\na_created 1 # {a="b"} 0.5\n# EOF\n'),
619630
# Exemplars on unallowed metric types.
620-
('# TYPE a counter\na_total 1 # {a="b"} 1\n# EOF\n'),
621631
('# TYPE a gauge\na 1 # {a="b"} 1\n# EOF\n'),
632+
('# TYPE a info\na_info 1 # {a="b"} 1\n# EOF\n'),
633+
('# TYPE a stateset\na{a="b"} 1 # {c="d"} 1\n# EOF\n'),
622634
# Bad stateset/info values.
623635
('# TYPE a stateset\na 2\n# EOF\n'),
624636
('# TYPE a info\na 2\n# EOF\n'),

0 commit comments

Comments
 (0)
0