mechanism to render metrics with alternative names
parent
80fa610f9c
commit
992018d1c0
|
@ -17,24 +17,33 @@
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
|
||||||
# TODO(paul): I can't believe Python doesn't have one of these
|
def flatten(items):
|
||||||
def map_concat(func, items):
|
"""Flatten a list of lists
|
||||||
# flatten a list-of-lists
|
|
||||||
return list(chain.from_iterable(map(func, items)))
|
Args:
|
||||||
|
items: iterable[iterable[X]]
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[X]: flattened list
|
||||||
|
"""
|
||||||
|
return list(chain.from_iterable(items))
|
||||||
|
|
||||||
|
|
||||||
class BaseMetric(object):
|
class BaseMetric(object):
|
||||||
"""Base class for metrics which report a single value per label set
|
"""Base class for metrics which report a single value per label set
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, labels=[]):
|
def __init__(self, name, labels=[], alternative_names=[]):
|
||||||
"""
|
"""
|
||||||
Args:
|
Args:
|
||||||
name (str): principal name for this metric
|
name (str): principal name for this metric
|
||||||
labels (list(str)): names of the labels which will be reported
|
labels (list(str)): names of the labels which will be reported
|
||||||
for this metric
|
for this metric
|
||||||
|
alternative_names (iterable(str)): list of alternative names for
|
||||||
|
this metric. This can be useful to provide a migration path
|
||||||
|
when renaming metrics.
|
||||||
"""
|
"""
|
||||||
self.name = name
|
self._names = [name] + list(alternative_names)
|
||||||
self.labels = labels # OK not to clone as we never write it
|
self.labels = labels # OK not to clone as we never write it
|
||||||
|
|
||||||
def dimension(self):
|
def dimension(self):
|
||||||
|
@ -55,6 +64,22 @@ class BaseMetric(object):
|
||||||
for k, v in zip(self.labels, values)])
|
for k, v in zip(self.labels, values)])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _render_for_labels(self, label_values, value):
|
||||||
|
"""Render this metric for a single set of labels
|
||||||
|
|
||||||
|
Args:
|
||||||
|
label_values (list[str]): values for each of the labels
|
||||||
|
value: value of the metric at with these labels
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
iterable[str]: rendered metric
|
||||||
|
"""
|
||||||
|
rendered_labels = self._render_key(label_values)
|
||||||
|
return (
|
||||||
|
"%s%s %.12g" % (name, rendered_labels, value)
|
||||||
|
for name in self._names
|
||||||
|
)
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
"""Render this metric
|
"""Render this metric
|
||||||
|
|
||||||
|
@ -110,11 +135,11 @@ class CounterMetric(BaseMetric):
|
||||||
def inc(self, *values):
|
def inc(self, *values):
|
||||||
self.inc_by(1, *values)
|
self.inc_by(1, *values)
|
||||||
|
|
||||||
def render_item(self, k):
|
|
||||||
return ["%s%s %.12g" % (self.name, self._render_key(k), self.counts[k])]
|
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
return map_concat(self.render_item, sorted(self.counts.keys()))
|
return flatten(
|
||||||
|
self._render_for_labels(k, self.counts[k])
|
||||||
|
for k in sorted(self.counts.keys())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CallbackMetric(BaseMetric):
|
class CallbackMetric(BaseMetric):
|
||||||
|
@ -131,10 +156,12 @@ class CallbackMetric(BaseMetric):
|
||||||
value = self.callback()
|
value = self.callback()
|
||||||
|
|
||||||
if self.is_scalar():
|
if self.is_scalar():
|
||||||
return ["%s %.12g" % (self.name, value)]
|
return list(self._render_for_labels([], value))
|
||||||
|
|
||||||
return ["%s%s %.12g" % (self.name, self._render_key(k), value[k])
|
return flatten(
|
||||||
for k in sorted(value.keys())]
|
self._render_for_labels(k, value[k])
|
||||||
|
for k in sorted(value.keys())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DistributionMetric(object):
|
class DistributionMetric(object):
|
||||||
|
|
Loading…
Reference in New Issue