Skip to content

Commit ab6be20

Browse files
authored
Parse escaped quotes in OpenMetrics exemplar label values (#1230)
The exemplar scanner in _parse_remaining_text flipped its in-quotes state on every double quote, so a label value like x"y, which the writer emits as x\"y, made the whole line fail with "Invalid line". Ignore quotes preceded by an odd number of backslashes. Signed-off-by: spicysharkco <321699413+spicysharkco@users.noreply.github.com>
1 parent fa7efa1 commit ab6be20

2 files changed

Lines changed: 13 additions & 3 deletions

File tree

‎prometheus_client/openmetrics/parser.py‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,9 @@ def _parse_remaining_text(text):
154154
state = 'timestamp'
155155
text = split_text[1]
156156

157-
it = iter(text)
158157
in_quotes = False
159-
for char in it:
160-
if char == '"':
158+
for i, char in enumerate(text):
159+
if char == '"' and not _is_character_escaped(text, i):
161160
in_quotes = not in_quotes
162161
if in_quotes:
163162
continue

‎tests/openmetrics/test_parser.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,17 @@ def test_label_escaping(self):
570570
metric_family.add_metric([unescaped_val, "baz"], 1)
571571
self.assertEqual([metric_family], list(families))
572572

573+
def test_exemplar_label_escaping(self):
574+
for escaped_val, unescaped_val in [('\\"', '"'), ('\\\\', '\\'), ('\\\\\\"', '\\"')]:
575+
families = list(text_string_to_metric_families("""# TYPE a counter
576+
# HELP a help
577+
a_total 1 # {foo="%s"} 1
578+
# EOF
579+
""" % escaped_val))
580+
metric_family = CounterMetricFamily("a", "help")
581+
metric_family.add_sample("a_total", {}, 1.0, None, Exemplar({"foo": unescaped_val}, 1))
582+
self.assertEqual([metric_family], list(families))
583+
573584
def test_help_escaping(self):
574585
for escaped_val, unescaped_val in [
575586
('foo', 'foo'),

0 commit comments

Comments
 (0)