Home | History | Annotate | Download | only in cros
      1 class Metric(object):
      2     """Abstract base class for metrics."""
      3     def __init__(self,
      4                  description,
      5                  units=None,
      6                  higher_is_better=False):
      7         """
      8         Initializes a Metric.
      9         @param description: Description of the metric, e.g., used as label on a
     10                 dashboard chart
     11         @param units: Units of the metric, e.g. percent, seconds, MB.
     12         @param higher_is_better: Whether a higher value is considered better or
     13                 not.
     14         """
     15         self.values = []
     16         self.description = description
     17         self.units = units
     18         self.higher_is_better = higher_is_better
     19 
     20     def collect_metric(self):
     21         """
     22         Collects one metric.
     23 
     24         Implementations should add a metric value to the self.values list.
     25         """
     26         raise NotImplementedError('Subclasses should override')
     27 
     28 class PeakMetric(Metric):
     29     """
     30     Metric that collects the peak of another metric.
     31     """
     32     def __init__(self, metric):
     33         """
     34         Initializes with a Metric.
     35 
     36         @param metric The Metric to get the peak from.
     37         """
     38         super(PeakMetric, self).__init__(
     39                 'peak_' + metric.description,
     40                 units = metric.units,
     41                 higher_is_better = metric.higher_is_better)
     42         self.metric = metric
     43 
     44     def collect_metric(self):
     45         self.values = [max(self.metric.values)] if self.metric.values else []
     46 
     47 class MemUsageMetric(Metric):
     48     """
     49     Metric that collects memory usage in percent.
     50 
     51     Memory usage is collected in percent. Buffers and cached are calculated
     52     as free memory.
     53     """
     54     def __init__(self, system_facade):
     55         super(MemUsageMetric, self).__init__('memory_usage', units='percent')
     56         self.system_facade = system_facade
     57 
     58     def collect_metric(self):
     59         total_memory = self.system_facade.get_mem_total()
     60         free_memory = self.system_facade.get_mem_free_plus_buffers_and_cached()
     61         used_memory = total_memory - free_memory
     62         usage_percent = (used_memory * 100) / total_memory
     63         self.values.append(usage_percent)
     64 
     65 class CpuUsageMetric(Metric):
     66     """
     67     Metric that collects cpu usage in percent.
     68     """
     69     def __init__(self, system_facade):
     70         super(CpuUsageMetric, self).__init__('cpu_usage', units='percent')
     71         self.last_usage = None
     72         self.system_facade = system_facade
     73 
     74     def collect_metric(self):
     75         """
     76         Collects CPU usage in percent.
     77 
     78         Since the CPU active time we query is a cumulative metric, the first
     79         collection does not actually save a value. It saves the first value to
     80         be used for subsequent deltas.
     81         """
     82         current_usage = self.system_facade.get_cpu_usage()
     83         if self.last_usage is not None:
     84             # Compute the percent of active time since the last update to
     85             # current_usage.
     86             usage_percent = 100 * self.system_facade.compute_active_cpu_time(
     87                     self.last_usage, current_usage)
     88             self.values.append(usage_percent)
     89         self.last_usage = current_usage
     90 
     91 class AllocatedFileHandlesMetric(Metric):
     92     """
     93     Metric that collects the number of allocated file handles.
     94     """
     95     def __init__(self, system_facade):
     96         super(AllocatedFileHandlesMetric, self).__init__(
     97                 'allocated_file_handles', units='handles')
     98         self.system_facade = system_facade
     99 
    100     def collect_metric(self):
    101         self.values.append(self.system_facade.get_num_allocated_file_handles())
    102 
    103 class TemperatureMetric(Metric):
    104     """
    105     Metric that collects the max of the temperatures measured on all sensors.
    106     """
    107     def __init__(self, system_facade):
    108         super(TemperatureMetric, self).__init__('temperature', units='Celsius')
    109         self.system_facade = system_facade
    110 
    111     def collect_metric(self):
    112         self.values.append(self.system_facade.get_current_temperature_max())
    113 
    114 def create_default_metric_set(system_facade):
    115     """
    116     Creates the default set of metrics.
    117 
    118     @param system_facade the system facade to initialize the metrics with.
    119     @return a list with Metric instances.
    120     """
    121     cpu = CpuUsageMetric(system_facade)
    122     mem = MemUsageMetric(system_facade)
    123     file_handles = AllocatedFileHandlesMetric(system_facade)
    124     temperature = TemperatureMetric(system_facade)
    125     peak_cpu = PeakMetric(cpu)
    126     peak_mem = PeakMetric(mem)
    127     peak_temperature = PeakMetric(temperature)
    128     return [cpu,
    129             mem,
    130             file_handles,
    131             temperature,
    132             peak_cpu,
    133             peak_mem,
    134             peak_temperature]
    135 
    136 class SystemMetricsCollector(object):
    137     """
    138     Collects system metrics.
    139     """
    140     def __init__(self, system_facade, metrics = None):
    141         """
    142         Initialize with facade and metric classes.
    143 
    144         @param system_facade The system facade to use for querying the system,
    145                 e.g. system_facade_native.SystemFacadeNative for client tests.
    146         @param metrics List of metric instances. If None, the default set will
    147                 be created.
    148         """
    149         self.metrics = (create_default_metric_set(system_facade)
    150                         if metrics is None else metrics)
    151 
    152     def collect_snapshot(self):
    153         """
    154         Collects one snapshot of metrics.
    155         """
    156         for metric in self.metrics:
    157             metric.collect_metric()
    158 
    159     def write_metrics(self, writer_function):
    160         """
    161         Writes the collected metrics using the specified writer function.
    162 
    163         @param writer_function: A function with the following signature:
    164                  f(description, value, units, higher_is_better)
    165         """
    166         for metric in self.metrics:
    167             writer_function(
    168                     description=metric.description,
    169                     value=metric.values,
    170                     units=metric.units,
    171                     higher_is_better=metric.higher_is_better)
    172