|
|
|
@ -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() |
|
|
|
|