mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2024-09-07 21:41:56 +00:00
Initial hack at a TimerMetric; for storing counts + duration accumulators
This commit is contained in:
parent
e1a7e3564f
commit
72625f2f4d
@ -14,6 +14,15 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(paul): I can't believe Python doesn't have one of these
|
||||||
|
def map_concat(func, items):
|
||||||
|
# flatten a list-of-lists
|
||||||
|
return list(chain.from_iterable(map(func, items)))
|
||||||
|
|
||||||
|
|
||||||
class BaseMetric(object):
|
class BaseMetric(object):
|
||||||
|
|
||||||
def __init__(self, name, keys=[]):
|
def __init__(self, name, keys=[]):
|
||||||
@ -87,6 +96,45 @@ class CallbackMetric(BaseMetric):
|
|||||||
return ["%s{%s} %d" % (self.name, self._render_key(k), value[k])
|
return ["%s{%s} %d" % (self.name, self._render_key(k), value[k])
|
||||||
for k in sorted(value.keys())]
|
for k in sorted(value.keys())]
|
||||||
|
|
||||||
|
|
||||||
|
class TimerMetric(CounterMetric):
|
||||||
|
"""A combination of an event counter and a time accumulator, which counts
|
||||||
|
both the number of events and how long each one takes.
|
||||||
|
|
||||||
|
TODO(paul): Try to export some heatmap-style stats?
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TimerMetric, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.times = {}
|
||||||
|
|
||||||
|
# Scalar metrics are never empty
|
||||||
|
if self.is_scalar():
|
||||||
|
self.times[()] = 0
|
||||||
|
|
||||||
|
def inc_time(self, msec, *values):
|
||||||
|
self.inc(*values)
|
||||||
|
|
||||||
|
if values not in self.times:
|
||||||
|
self.times[values] = msec
|
||||||
|
else:
|
||||||
|
self.times[values] += msec
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
if self.is_scalar():
|
||||||
|
return ["%s:count %d" % (self.name, self.counts[()]),
|
||||||
|
"%s:msec %d" % (self.name, self.times[()])]
|
||||||
|
|
||||||
|
def render_item(k):
|
||||||
|
keystr = self._render_key(k)
|
||||||
|
|
||||||
|
return ["%s{%s}:count %d" % (self.name, keystr, self.counts[k]),
|
||||||
|
"%s{%s}:msec %d" % (self.name, keystr, self.times[k])]
|
||||||
|
|
||||||
|
return map_concat(render_item, sorted(self.counts.keys()))
|
||||||
|
|
||||||
|
|
||||||
class CacheMetric(object):
|
class CacheMetric(object):
|
||||||
"""A combination of two CounterMetrics, one to count cache hits and one to
|
"""A combination of two CounterMetrics, one to count cache hits and one to
|
||||||
count misses, and a callback metric to yield the current size.
|
count misses, and a callback metric to yield the current size.
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
from tests import unittest
|
from tests import unittest
|
||||||
|
|
||||||
from synapse.metrics.metric import (
|
from synapse.metrics.metric import (
|
||||||
CounterMetric, CallbackMetric, CacheMetric
|
CounterMetric, CallbackMetric, TimerMetric, CacheMetric
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +97,40 @@ class CallbackMetricTestCase(unittest.TestCase):
|
|||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class TimerMetricTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_scalar(self):
|
||||||
|
metric = TimerMetric("thing")
|
||||||
|
|
||||||
|
self.assertEquals(metric.render(), [
|
||||||
|
"thing:count 0",
|
||||||
|
"thing:msec 0",
|
||||||
|
])
|
||||||
|
|
||||||
|
metric.inc_time(500)
|
||||||
|
|
||||||
|
self.assertEquals(metric.render(), [
|
||||||
|
"thing:count 1",
|
||||||
|
"thing:msec 500",
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_vector(self):
|
||||||
|
metric = TimerMetric("queries", keys=["verb"])
|
||||||
|
|
||||||
|
self.assertEquals(metric.render(), [])
|
||||||
|
|
||||||
|
metric.inc_time(300, "SELECT")
|
||||||
|
metric.inc_time(200, "SELECT")
|
||||||
|
metric.inc_time(800, "INSERT")
|
||||||
|
|
||||||
|
self.assertEquals(metric.render(), [
|
||||||
|
"queries{verb=INSERT}:count 1",
|
||||||
|
"queries{verb=INSERT}:msec 800",
|
||||||
|
"queries{verb=SELECT}:count 2",
|
||||||
|
"queries{verb=SELECT}:msec 500",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class CacheMetricTestCase(unittest.TestCase):
|
class CacheMetricTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def test_cache(self):
|
def test_cache(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user