diff options
Diffstat (limited to 'synapse')
-rw-r--r-- | synapse/metrics/__init__.py | 11 | ||||
-rw-r--r-- | synapse/metrics/metric.py | 43 |
2 files changed, 47 insertions, 7 deletions
diff --git a/synapse/metrics/__init__.py b/synapse/metrics/__init__.py index 125845eb30..d5c30bbe41 100644 --- a/synapse/metrics/__init__.py +++ b/synapse/metrics/__init__.py @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .metric import CounterMetric +from .metric import CounterMetric, CacheCounterMetric # We'll keep all the available metrics in a single toplevel dict, one shared @@ -43,6 +43,15 @@ class Metrics(object): return metric + def register_cachecounter(self, name, *args, **kwargs): + full_name = "%s.%s" % (self.name_prefix, name) + + metric = CacheCounterMetric(full_name, *args, **kwargs) + + self._register(metric) + + return metric + def counted(self, func): """ A method decorator that registers a counter, to count invocations of this method. """ diff --git a/synapse/metrics/metric.py b/synapse/metrics/metric.py index f5a98763cc..00b149f6f6 100644 --- a/synapse/metrics/metric.py +++ b/synapse/metrics/metric.py @@ -14,16 +14,28 @@ # limitations under the License. -class CounterMetric(object): +class BaseMetric(object): def __init__(self, name, keys=[]): self.name = name self.keys = keys # OK not to clone as we never write it + def _render_key(self, values): + # TODO: some kind of value escape + return ",".join(["%s=%s" % kv for kv in zip(self.keys, values)]) + + +class CounterMetric(BaseMetric): + """The simplest kind of metric; one that stores a monotonically-increasing + integer that counts events.""" + + def __init__(self, *args, **kwargs): + super(CounterMetric, self).__init__(*args, **kwargs) + self.counts = {} # Scalar metrics are never empty - if not len(keys): + if not len(self.keys): self.counts[()] = 0 def inc(self, *values): @@ -42,13 +54,32 @@ class CounterMetric(object): def fetch(self): return dict(self.counts) - def _render_key(self, values): - # TODO: some kind of value escape - return ",".join(["%s=%s" % kv for kv in zip(self.keys, values)]) - def render(self): if not len(self.keys): return ["%s %d" % (self.name, self.counts[()])] return ["%s{%s} %d" % (self.name, self._render_key(k), self.counts[k]) for k in sorted(self.counts.keys())] + + +class CacheCounterMetric(object): + """A combination of two CounterMetrics, one to count cache hits and one to + count misses. + + This metric generates standard metric name pairs, so that monitoring rules + can easily be applied to measure hit ratio.""" + + def __init__(self, name, keys=[]): + self.name = name + + self.hits = CounterMetric(name + ":hits", keys=keys) + self.misses = CounterMetric(name + ":misses", keys=keys) + + def inc_hits(self, *values): + self.hits.inc(*values) + + def inc_misses(self, *values): + self.misses.inc(*values) + + def render(self): + return self.hits.render() + self.misses.render() |