Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Unified Diff: client/third_party/infra_libs/ts_mon/common/metrics.py

Issue 2991803002: Update infra_libs to 1.1.15 / 0b44aba87c1c6538439df6d24a409870810747ab (Closed)
Patch Set: fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: client/third_party/infra_libs/ts_mon/common/metrics.py
diff --git a/client/third_party/infra_libs/ts_mon/common/metrics.py b/client/third_party/infra_libs/ts_mon/common/metrics.py
index 9cb565abca6f178f1122c9f2c8da6fad8ebcedee..5ef401c34e96ec46981ae32110cd3026108bb78f 100644
--- a/client/third_party/infra_libs/ts_mon/common/metrics.py
+++ b/client/third_party/infra_libs/ts_mon/common/metrics.py
@@ -7,8 +7,7 @@
import copy
import re
-from infra_libs.ts_mon.protos.current import metrics_pb2
-from infra_libs.ts_mon.protos.new import metrics_pb2 as new_metrics_pb2
+from infra_libs.ts_mon.protos import metrics_pb2
from infra_libs.ts_mon.common import distribution
from infra_libs.ts_mon.common import errors
@@ -22,10 +21,8 @@ class Field(object):
FIELD_NAME_PATTERN = re.compile(r'[A-Za-z_][A-Za-z0-9_]*')
allowed_python_types = None
- v1_type = None
- v2_type = None
- v1_field = None
- v2_field = None
+ type_enum = None
+ field_name = None
def __init__(self, name):
if not self.FIELD_NAME_PATTERN.match(name):
@@ -40,35 +37,26 @@ class Field(object):
raise errors.MonitoringInvalidFieldTypeError(
metric_name, self.name, value)
- def populate_proto_v1(self, proto, value):
- setattr(proto, self.v1_field, value)
-
- def populate_proto_v2(self, proto, value):
- setattr(proto, self.v2_field, value)
+ def populate_proto(self, proto, value):
+ setattr(proto, self.field_name, value)
class StringField(Field):
allowed_python_types = basestring
- v1_type = metrics_pb2.MetricsField.STRING
- v2_type = new_metrics_pb2.MetricsDataSet.MetricFieldDescriptor.STRING
- v1_field = 'string_value'
- v2_field = 'string_value'
+ type_enum = metrics_pb2.MetricsDataSet.MetricFieldDescriptor.STRING
+ field_name = 'string_value'
class IntegerField(Field):
allowed_python_types = (int, long)
- v1_type = metrics_pb2.MetricsField.INT
- v2_type = new_metrics_pb2.MetricsDataSet.MetricFieldDescriptor.INT64
- v1_field = 'int_value'
- v2_field = 'int64_value'
+ type_enum = metrics_pb2.MetricsDataSet.MetricFieldDescriptor.INT64
+ field_name = 'int64_value'
class BooleanField(Field):
allowed_python_types = bool
- v1_type = metrics_pb2.MetricsField.BOOL
- v2_type = new_metrics_pb2.MetricsDataSet.MetricFieldDescriptor.BOOL
- v1_field = 'bool_value'
- v2_field = 'bool_value'
+ type_enum = metrics_pb2.MetricsDataSet.MetricFieldDescriptor.BOOL
+ field_name = 'bool_value'
class Metric(object):
@@ -87,11 +75,10 @@ class Metric(object):
set() or increment() methods to modify a particular value, or passed to the
constructor in which case they will be used as the defaults for this Metric.
- The unit of measurement for Metric data can be specified with MetricsDataUnits
- when a Metric object is created:
+ The unit of measurement for Metric data should be specified with
+ MetricsDataUnits when a Metric object is created:
e.g., MetricsDataUnits.SECONDS, MetricsDataUnits.BYTES, and etc..,
- A full list of supported units can be found in the following protobuf file
- : infra_libs/ts_mon/protos/metrics.proto
+ See `MetricsDataUnits` class for a full list of units.
Do not directly instantiate an object of this class.
Use the concrete child classes instead:
@@ -115,9 +102,9 @@ class Metric(object):
field_spec (list): a list of Field subclasses to define the fields that
are allowed on this metric. Pass a list of either
StringField, IntegerField or BooleanField here.
- units (int): the unit used to measure data for given
- metric. Please use the attributes of MetricDataUnit to find
- valid integer values for this argument.
+ units (string): the unit used to measure data for given metric. Some
+ common units are pre-defined in the MetricsDataUnits
+ class.
"""
field_spec = field_spec or []
@@ -143,6 +130,10 @@ class Metric(object):
interface.register(self)
@property
+ def field_spec(self):
+ return list(self._field_spec)
+
+ @property
def name(self):
return self._name
@@ -150,84 +141,58 @@ class Metric(object):
def start_time(self):
return self._start_time
+ @property
+ def units(self):
+ return self._units
+
def is_cumulative(self):
raise NotImplementedError()
def unregister(self):
interface.unregister(self)
- @staticmethod
- def _map_units_to_string(units):
- """Map MetricsDataUnits to the corresponding string according to:
- http://unitsofmeasure.org/ucum.html because that's what the new proto
- requires."""
- if units in _UNITS_TO_STRING:
- return _UNITS_TO_STRING[units]
- else:
- return '{unknown}'
-
- def _populate_data_set(self, data_set):
+ def populate_data_set(self, data_set):
"""Populate MetricsDataSet."""
data_set.metric_name = '%s%s' % (interface.state.metric_name_prefix,
self._name)
data_set.description = self._description or ''
- data_set.annotations.unit = self._map_units_to_string(self._units)
+ if self._units is not None:
+ data_set.annotations.unit = self._units
if self.is_cumulative():
- data_set.stream_kind = new_metrics_pb2.CUMULATIVE
+ data_set.stream_kind = metrics_pb2.CUMULATIVE
else:
- data_set.stream_kind = new_metrics_pb2.GAUGE
+ data_set.stream_kind = metrics_pb2.GAUGE
self._populate_value_type(data_set)
self._populate_field_descriptors(data_set)
- def _populate_data(self, data, start_time, end_time, fields, value):
+ def populate_data(self, data, start_time, end_time, fields, value):
"""Populate a new metrics_pb2.MetricsData.
Args:
- data_ (new_metrics_pb2.MetricsData): protocol buffer into
+ data (metrics_pb2.MetricsData): protocol buffer into
which to populate the current metric values.
start_time (int): timestamp in microseconds since UNIX epoch.
"""
data.start_timestamp.seconds = int(start_time)
data.end_timestamp.seconds = int(end_time)
- self._populate_fields_new(data, fields)
- self._populate_value_new(data, value)
-
- def serialize_to(self, metric_pb, start_time, fields, value, target):
- """Generate metrics_pb2.MetricsData messages for this metric.
-
- Args:
- metric_pb (metrics_pb2.MetricsData): protocol buffer into which
- to serialize the current metric values.
- start_time (int): timestamp in microseconds since UNIX epoch.
- target (Target): a Target to use.
- """
-
- metric_pb.metric_name_prefix = interface.state.metric_name_prefix
- metric_pb.name = self._name
- metric_pb.description = self._description
- if self._units is not None:
- metric_pb.units = self._units
-
- self._populate_value(metric_pb, value, start_time)
- self._populate_fields(metric_pb, fields)
-
- target._populate_target_pb(metric_pb)
+ self._populate_fields(data, fields)
+ self._populate_value(data, value)
def _populate_field_descriptors(self, data_set):
"""Populate `field_descriptor` in MetricsDataSet.
Args:
- data_set (new_metrics_pb2.MetricsDataSet): a data set protobuf to populate
+ data_set (metrics_pb2.MetricsDataSet): a data set protobuf to populate
"""
for spec in self._field_spec:
descriptor = data_set.field_descriptor.add()
descriptor.name = spec.name
- descriptor.field_type = spec.v2_type
+ descriptor.field_type = spec.type_enum
- def _populate_fields_new(self, data, field_values):
+ def _populate_fields(self, data, field_values):
"""Fill in the fields attribute of a metric protocol buffer.
Args:
@@ -237,20 +202,7 @@ class Metric(object):
for spec, value in zip(self._field_spec, field_values):
field = data.field.add()
field.name = spec.name
- spec.populate_proto_v2(field, value)
-
- def _populate_fields(self, metric, field_values):
- """Fill in the fields attribute of a metric protocol buffer.
-
- Args:
- metric (metrics_pb2.MetricsData): a metrics protobuf to populate
- field_values (tuple): field values
- """
- for spec, value in zip(self._field_spec, field_values):
- field = metric.fields.add()
- field.name = spec.name
- field.type = spec.v1_type
- spec.populate_proto_v1(field, value)
+ spec.populate_proto(field, value)
def _validate_fields(self, fields):
"""Checks the correct number and types of field values were provided.
@@ -282,17 +234,7 @@ class Metric(object):
return tuple(fields[spec.name] for spec in self._field_spec)
- def _populate_value(self, metric, value, start_time):
- """Fill in the the data values of a metric protocol buffer.
-
- Args:
- metric (metrics_pb2.MetricsData): a metrics protobuf to populate
- value (see concrete class): the value of the metric to be set
- start_time (int): timestamp in microseconds since UNIX epoch.
- """
- raise NotImplementedError()
-
- def _populate_value_new(self, data, value):
+ def _populate_value(self, data, value):
"""Fill in the the data values of a metric protocol buffer.
Args:
@@ -358,14 +300,11 @@ class Metric(object):
class StringMetric(Metric):
"""A metric whose value type is a string."""
- def _populate_value(self, metric, value, start_time):
- metric.string_value = value
-
- def _populate_value_new(self, data, value):
+ def _populate_value(self, data, value):
data.string_value = value
def _populate_value_type(self, data_set):
- data_set.value_type = new_metrics_pb2.STRING
+ data_set.value_type = metrics_pb2.STRING
def set(self, value, fields=None, target_fields=None):
if not isinstance(value, basestring):
@@ -379,14 +318,11 @@ class StringMetric(Metric):
class BooleanMetric(Metric):
"""A metric whose value type is a boolean."""
- def _populate_value(self, metric, value, start_time):
- metric.boolean_value = value
-
- def _populate_value_new(self, data, value):
+ def _populate_value(self, data, value):
data.bool_value = value
def _populate_value_type(self, data_set):
- data_set.value_type = new_metrics_pb2.BOOL
+ data_set.value_type = metrics_pb2.BOOL
def set(self, value, fields=None, target_fields=None):
if not isinstance(value, bool):
@@ -410,21 +346,17 @@ class NumericMetric(Metric): # pylint: disable=abstract-method
class CounterMetric(NumericMetric):
"""A metric whose value type is a monotonically increasing integer."""
- def __init__(self, name, description, field_spec=None, start_time=None,
+ def __init__(self, name, description, field_spec, start_time=None,
units=None):
super(CounterMetric, self).__init__(
name, description, field_spec, units=units)
self._start_time = start_time
- def _populate_value(self, metric, value, start_time):
- metric.counter = value
- metric.start_timestamp_us = int(start_time * MICROSECONDS_PER_SECOND)
-
- def _populate_value_new(self, data, value):
+ def _populate_value(self, data, value):
data.int64_value = value
def _populate_value_type(self, data_set):
- data_set.value_type = new_metrics_pb2.INT64
+ data_set.value_type = metrics_pb2.INT64
def set(self, value, fields=None, target_fields=None):
if not isinstance(value, (int, long)):
@@ -443,14 +375,11 @@ class CounterMetric(NumericMetric):
class GaugeMetric(NumericMetric):
"""A metric whose value type is an integer."""
- def _populate_value(self, metric, value, start_time):
- metric.gauge = value
-
- def _populate_value_new(self, data, value):
+ def _populate_value(self, data, value):
data.int64_value = value
def _populate_value_type(self, data_set):
- data_set.value_type = new_metrics_pb2.INT64
+ data_set.value_type = metrics_pb2.INT64
def set(self, value, fields=None, target_fields=None):
if not isinstance(value, (int, long)):
@@ -464,21 +393,17 @@ class GaugeMetric(NumericMetric):
class CumulativeMetric(NumericMetric):
"""A metric whose value type is a monotonically increasing float."""
- def __init__(self, name, description, field_spec=None, start_time=None,
+ def __init__(self, name, description, field_spec, start_time=None,
units=None):
super(CumulativeMetric, self).__init__(
name, description, field_spec, units=units)
self._start_time = start_time
- def _populate_value(self, metric, value, start_time):
- metric.cumulative_double_value = value
- metric.start_timestamp_us = int(start_time * MICROSECONDS_PER_SECOND)
-
- def _populate_value_new(self, data, value):
+ def _populate_value(self, data, value):
data.double_value = value
def _populate_value_type(self, data_set):
- data_set.value_type = new_metrics_pb2.DOUBLE
+ data_set.value_type = metrics_pb2.DOUBLE
def set(self, value, fields=None, target_fields=None):
if not isinstance(value, (float, int)):
@@ -492,14 +417,11 @@ class CumulativeMetric(NumericMetric):
class FloatMetric(NumericMetric):
"""A metric whose value type is a float."""
- def _populate_value(self, metric, value, start_time):
- metric.noncumulative_double_value = value
-
- def _populate_value_new(self, metric, value):
+ def _populate_value(self, metric, value):
metric.double_value = value
def _populate_value_type(self, data_set_pb):
- data_set_pb.value_type = new_metrics_pb2.DOUBLE
+ data_set_pb.value_type = metrics_pb2.DOUBLE
def set(self, value, fields=None, target_fields=None):
if not isinstance(value, (float, int)):
@@ -518,13 +440,7 @@ class _DistributionMetricBase(Metric):
for many kinds of data, but you may want to provide a FixedWidthBucketer or
GeometricBucketer with different parameters."""
- CANONICAL_SPEC_TYPES = {
- 2: metrics_pb2.PrecomputedDistribution.CANONICAL_POWERS_OF_2,
- 10**0.2: metrics_pb2.PrecomputedDistribution.CANONICAL_POWERS_OF_10_P_0_2,
- 10: metrics_pb2.PrecomputedDistribution.CANONICAL_POWERS_OF_10,
- }
-
- def __init__(self, name, description, field_spec=None, is_cumulative=True,
+ def __init__(self, name, description, field_spec, is_cumulative=True,
bucketer=None, start_time=None, units=None):
super(_DistributionMetricBase, self).__init__(
name, description, field_spec, units=units)
@@ -536,45 +452,13 @@ class _DistributionMetricBase(Metric):
self._is_cumulative = is_cumulative
self.bucketer = bucketer
- def _populate_value(self, metric, value, start_time):
- pb = metric.distribution
-
- pb.is_cumulative = self._is_cumulative
- if self._is_cumulative:
- metric.start_timestamp_us = int(start_time * MICROSECONDS_PER_SECOND)
-
- # Copy the bucketer params.
- if (value.bucketer.width == 0 and
- value.bucketer.growth_factor in self.CANONICAL_SPEC_TYPES):
- pb.spec_type = self.CANONICAL_SPEC_TYPES[value.bucketer.growth_factor]
- else:
- pb.spec_type = metrics_pb2.PrecomputedDistribution.CUSTOM_PARAMETERIZED
- pb.width = value.bucketer.width
- pb.growth_factor = value.bucketer.growth_factor
- pb.num_buckets = value.bucketer.num_finite_buckets
-
- # Copy the distribution bucket values. Only include the finite buckets, not
- # the overflow buckets on each end.
- pb.bucket.extend(self._running_zero_generator(
- value.buckets.get(i, 0) for i in
- xrange(1, value.bucketer.total_buckets - 1)))
-
- # Add the overflow buckets if present.
- if value.bucketer.underflow_bucket in value.buckets:
- pb.underflow = value.buckets[value.bucketer.underflow_bucket]
- if value.bucketer.overflow_bucket in value.buckets:
- pb.overflow = value.buckets[value.bucketer.overflow_bucket]
-
- if value.count != 0:
- pb.mean = float(value.sum) / value.count
-
- def _populate_value_new(self, metric, value):
+ def _populate_value(self, metric, value):
pb = metric.distribution_value
# Copy the bucketer params.
if value.bucketer.width == 0:
pb.exponential_buckets.growth_factor = value.bucketer.growth_factor
- pb.exponential_buckets.scale = 1.0
+ pb.exponential_buckets.scale = value.bucketer.scale
pb.exponential_buckets.num_finite_buckets = (
value.bucketer.num_finite_buckets)
else:
@@ -592,25 +476,7 @@ class _DistributionMetricBase(Metric):
pb.mean = float(value.sum) / max(value.count, 1)
def _populate_value_type(self, data_set_pb):
- data_set_pb.value_type = new_metrics_pb2.DISTRIBUTION
-
- @staticmethod
- def _running_zero_generator(iterable):
- """Compresses sequences of zeroes in the iterable into negative zero counts.
-
- For example an input of [1, 0, 0, 0, 2] is converted to [1, -3, 2].
- """
-
- count = 0
-
- for value in iterable:
- if value == 0:
- count += 1
- else:
- if count != 0:
- yield -count
- count = 0
- yield value
+ data_set_pb.value_type = metrics_pb2.DISTRIBUTION
def add(self, value, fields=None, target_fields=None):
def modify_fn(dist, value):
@@ -646,8 +512,7 @@ class _DistributionMetricBase(Metric):
class CumulativeDistributionMetric(_DistributionMetricBase):
"""A DistributionMetric with is_cumulative set to True."""
- def __init__(self, name, description, field_spec=None, bucketer=None,
- units=None):
+ def __init__(self, name, description, field_spec, bucketer=None, units=None):
super(CumulativeDistributionMetric, self).__init__(
name, description, field_spec,
is_cumulative=True,
@@ -658,8 +523,7 @@ class CumulativeDistributionMetric(_DistributionMetricBase):
class NonCumulativeDistributionMetric(_DistributionMetricBase):
"""A DistributionMetric with is_cumulative set to False."""
- def __init__(self, name, description, field_spec=None, bucketer=None,
- units=None):
+ def __init__(self, name, description, field_spec, bucketer=None, units=None):
super(NonCumulativeDistributionMetric, self).__init__(
name, description, field_spec,
is_cumulative=False,
@@ -667,34 +531,22 @@ class NonCumulativeDistributionMetric(_DistributionMetricBase):
units=units)
-class MetaMetricsDataUnits(type):
- """Metaclass to populate the enum values of metrics_pb2.MetricsData.Units."""
- def __new__(mcs, name, bases, attrs):
- attrs.update(metrics_pb2.MetricsData.Units.items())
- return super(MetaMetricsDataUnits, mcs).__new__(mcs, name, bases, attrs)
-
-
class MetricsDataUnits(object):
- """An enumeration class for units of measurement for Metrics data.
- See infra_libs/ts_mon/protos/metrics.proto for a full list of supported units.
- """
- __metaclass__ = MetaMetricsDataUnits
-
-_UNITS_TO_STRING = {
- MetricsDataUnits.UNKNOWN_UNITS: '{unknown}',
- MetricsDataUnits.SECONDS: 's',
- MetricsDataUnits.MILLISECONDS: 'ms',
- MetricsDataUnits.MICROSECONDS: 'us',
- MetricsDataUnits.NANOSECONDS: 'ns',
- MetricsDataUnits.BITS: 'B',
- MetricsDataUnits.BYTES: 'By',
- MetricsDataUnits.KILOBYTES: 'kBy',
- MetricsDataUnits.MEGABYTES: 'MBy',
- MetricsDataUnits.GIGABYTES: 'GBy',
- MetricsDataUnits.KIBIBYTES: 'kiBy',
- MetricsDataUnits.MEBIBYTES: 'MiBy',
- MetricsDataUnits.GIBIBYTES: 'GiBy',
- MetricsDataUnits.AMPS: 'A',
- MetricsDataUnits.MILLIAMPS : 'mA',
- MetricsDataUnits.DEGREES_CELSIUS: 'Cel'
-}
+ """An container for units of measurement for Metrics data."""
+
+ UNKNOWN_UNITS = '{unknown}'
+ SECONDS = 's'
+ MILLISECONDS = 'ms'
+ MICROSECONDS = 'us'
+ NANOSECONDS = 'ns'
+ BITS = 'B'
+ BYTES = 'By'
+ KILOBYTES = 'kBy'
+ MEGABYTES = 'MBy'
+ GIGABYTES = 'GBy'
+ KIBIBYTES = 'kiBy'
+ MEBIBYTES = 'MiBy'
+ GIBIBYTES = 'GiBy'
+ AMPS = 'A'
+ MILLIAMPS = 'mA'
+ DEGREES_CELSIUS = 'Cel'
« no previous file with comments | « client/third_party/infra_libs/ts_mon/common/metric_store.py ('k') | client/third_party/infra_libs/ts_mon/common/monitors.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698