Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3175 from matrix-org/erikj/escape_metric_values
Browse files Browse the repository at this point in the history
Escape label values in prometheus metrics
  • Loading branch information
erikjohnston authored May 3, 2018
2 parents 3a42aed + a41117c commit 53a5fdf
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
30 changes: 28 additions & 2 deletions synapse/metrics/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

from itertools import chain
import logging
import re

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -56,8 +57,7 @@ def is_scalar(self):
return not len(self.labels)

def _render_labelvalue(self, value):
# TODO: escape backslashes, quotes and newlines
return '"%s"' % (value)
return '"%s"' % (_escape_label_value(value),)

def _render_key(self, values):
if self.is_scalar():
Expand Down Expand Up @@ -299,3 +299,29 @@ def render(self):
"process_psutil_rss:total %d" % sum_rss,
"process_psutil_rss:count %d" % len_rss,
]


def _escape_character(m):
"""Replaces a single character with its escape sequence.
Args:
m (re.MatchObject): A match object whose first group is the single
character to replace
Returns:
str
"""
c = m.group(1)
if c == "\\":
return "\\\\"
elif c == "\"":
return "\\\""
elif c == "\n":
return "\\n"
return c


def _escape_label_value(value):
"""Takes a label value and escapes quotes, newlines and backslashes
"""
return re.sub(r"([\n\"\\])", _escape_character, value)
21 changes: 20 additions & 1 deletion tests/metrics/test_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
from tests import unittest

from synapse.metrics.metric import (
CounterMetric, CallbackMetric, DistributionMetric, CacheMetric
CounterMetric, CallbackMetric, DistributionMetric, CacheMetric,
_escape_label_value,
)


Expand Down Expand Up @@ -171,3 +172,21 @@ def test_cache(self):
'cache:size{name="cache_name"} 1',
'cache:evicted_size{name="cache_name"} 2',
])


class LabelValueEscapeTestCase(unittest.TestCase):
def test_simple(self):
string = "safjhsdlifhyskljfksdfh"
self.assertEqual(string, _escape_label_value(string))

def test_escape(self):
self.assertEqual(
"abc\\\"def\\nghi\\\\",
_escape_label_value("abc\"def\nghi\\"),
)

def test_sequence_of_escapes(self):
self.assertEqual(
"abc\\\"def\\nghi\\\\\\n",
_escape_label_value("abc\"def\nghi\\\n"),
)

0 comments on commit 53a5fdf

Please sign in to comment.