Skip to content

Commit

Permalink
Prevent ':' to reach metric unique name in StatsD
Browse files Browse the repository at this point in the history
  • Loading branch information
leplatrem committed Dec 10, 2024
1 parent b1cc6da commit d1be3cc
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 2 deletions.
12 changes: 10 additions & 2 deletions kinto/plugins/statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
statsd_module = None


def sanitize(value):
"""
Telegraf does not support ':' in values.
See https://github.com/influxdata/telegraf/issues/4495
"""
return value.replace(":", "") if isinstance(value, str) else value


@implementer(metrics.IMetricsService)
class StatsDService:
def __init__(self, host, port, prefix):
Expand All @@ -22,15 +30,15 @@ def timer(self, key):
return self._client.timer(key)

def observe(self, key, value, labels=[]):
return self._client.gauge(key, value)
return self._client.gauge(key, sanitize(value))

def count(self, key, count=1, unique=None):
if unique is None:
return self._client.incr(key, count=count)
if isinstance(unique, list):
# [("method", "get")] -> "method.get"
# [("endpoint", "/"), ("method", "get")] -> "endpoint./.method.get"
unique = ".".join(f"{label[0]}.{label[1]}" for label in unique)
unique = ".".join(f"{label[0]}.{sanitize(label[1])}" for label in unique)
else:
warnings.warn(
"`unique` parameter should be of type ``list[tuple[str, str]]``",
Expand Down
5 changes: 5 additions & 0 deletions tests/plugins/test_statsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ def test_count_turns_multiple_tuples_into_one_set_key(self):
self.client.count("click", unique=[("component", "menu"), ("sound", "off")])
mocked_client.set.assert_called_with("click", "component.menu.sound.off")

def test_values_are_sanitized(self):
with mock.patch.object(self.client, "_client") as mocked_client:
self.client.count("click", unique=[("user", "account:boss")])
mocked_client.set.assert_called_with("click", "user.accountboss")

@mock.patch("kinto.plugins.statsd.statsd_module")
def test_load_from_config(self, module_mock):
config = testing.setUp()
Expand Down

0 comments on commit d1be3cc

Please sign in to comment.