diff --git a/prometheus_client/openmetrics/parser.py b/prometheus_client/openmetrics/parser.py index 0c5c9c41..adb3a388 100644 --- a/prometheus_client/openmetrics/parser.py +++ b/prometheus_client/openmetrics/parser.py @@ -154,10 +154,9 @@ def _parse_remaining_text(text): state = 'timestamp' text = split_text[1] - it = iter(text) in_quotes = False - for char in it: - if char == '"': + for i, char in enumerate(text): + if char == '"' and not _is_character_escaped(text, i): in_quotes = not in_quotes if in_quotes: continue diff --git a/tests/openmetrics/test_parser.py b/tests/openmetrics/test_parser.py index 79a2158c..684d9a82 100644 --- a/tests/openmetrics/test_parser.py +++ b/tests/openmetrics/test_parser.py @@ -570,6 +570,17 @@ def test_label_escaping(self): metric_family.add_metric([unescaped_val, "baz"], 1) self.assertEqual([metric_family], list(families)) + def test_exemplar_label_escaping(self): + for escaped_val, unescaped_val in [('\\"', '"'), ('\\\\', '\\'), ('\\\\\\"', '\\"')]: + families = list(text_string_to_metric_families("""# TYPE a counter +# HELP a help +a_total 1 # {foo="%s"} 1 +# EOF +""" % escaped_val)) + metric_family = CounterMetricFamily("a", "help") + metric_family.add_sample("a_total", {}, 1.0, None, Exemplar({"foo": unescaped_val}, 1)) + self.assertEqual([metric_family], list(families)) + def test_help_escaping(self): for escaped_val, unescaped_val in [ ('foo', 'foo'),