diff --git a/synapse/metrics/metric.py b/synapse/metrics/metric.py
index e8c15a60e8..4df5ebfda6 100644
--- a/synapse/metrics/metric.py
+++ b/synapse/metrics/metric.py
@@ -79,9 +79,13 @@ class CallbackMetric(BaseMetric):
self.callback = callback
def render(self):
- # TODO(paul): work out something we can do with keys and vectors
- return ["%s %d" % (self.name, self.callback())]
+ value = self.callback()
+ if self.is_scalar():
+ return ["%s %d" % (self.name, value)]
+
+ return ["%s{%s} %d" % (self.name, self._render_key(k), value[k])
+ for k in sorted(value.keys())]
class CacheMetric(object):
"""A combination of two CounterMetrics, one to count cache hits and one to
diff --git a/tests/metrics/test_metric.py b/tests/metrics/test_metric.py
index 32fd178ed4..b7facb8587 100644
--- a/tests/metrics/test_metric.py
+++ b/tests/metrics/test_metric.py
@@ -65,7 +65,7 @@ class CounterMetricTestCase(unittest.TestCase):
class CallbackMetricTestCase(unittest.TestCase):
- def test_callback(self):
+ def test_scalar(self):
d = dict()
metric = CallbackMetric("size", lambda: len(d))
@@ -80,6 +80,22 @@ class CallbackMetricTestCase(unittest.TestCase):
"size 1",
])
+ def test_vector(self):
+ vals = dict()
+
+ metric = CallbackMetric("values", lambda: vals, keys=["type"])
+
+ self.assertEquals(metric.render(), [])
+
+ # Keys have to be tuples, even if they're 1-element
+ vals[("foo",)] = 1
+ vals[("bar",)] = 2
+
+ self.assertEquals(metric.render(), [
+ "values{type=bar} 2",
+ "values{type=foo} 1",
+ ])
+
class CacheMetricTestCase(unittest.TestCase):
|