Home | History | Annotate | Download | only in metrics
      1 from __future__ import division
      2 
      3 from autotest_lib.client.common_lib.cros.cfm.metrics import (
      4         media_info_metrics_extractor)
      5 
      6 MEDIA_TYPE = media_info_metrics_extractor.MediaType
      7 DIRECTION = media_info_metrics_extractor.Direction
      8 
      9 # Delta used to determine if floating point values are equal.
     10 FLOATING_POINT_COMPARISON_DELTA = 0.00001
     11 
     12 def _avg(l):
     13     """
     14     Returns the average of the list or 0 if the list is empty.
     15     """
     16     return sum(l)/len(l) if l else 0
     17 
     18 
     19 def _max(l):
     20     """
     21     Returns the max of the list or 0 if the list is empty.
     22     """
     23     return max(l) if l else 0
     24 
     25 
     26 def _get_number_of_incoming_active_video_streams(extractor):
     27     """
     28     Calculates the number of incoming video streams.
     29 
     30     @param extractor media_info_metrics_extractor.MediaInfoMetricsExtractor.
     31 
     32     @returns List with (timestamp, number of incoming video streams) tuples.
     33     """
     34     # Get metrics of a kind we know exists and count the nuber of values
     35     # for each data point.
     36     fps_metrics = extractor.get_media_metric(
     37             'fps', direction=DIRECTION.RECEIVER, media_type=MEDIA_TYPE.VIDEO)
     38     return [(x, [len(y)]) for x, y in fps_metrics]
     39 
     40 
     41 # Sum for all received streams per data point.
     42 BROWSER_CPU_PERCENT_OF_TOTAL = 'browser_cpu_percent'
     43 CPU_PERCENT_OF_TOTAL = 'cpu_percent'
     44 FRAMERATE_CAPTURED = 'framerate_catured'
     45 # Mean for all received streams per data point.
     46 FRAMERATE_DECODED = 'framerate_decoded'
     47 # Max for all received streams per data point.
     48 FRAMERATE_DECODED_MAX = 'framerate_decoded_max'
     49 # Mean for all received streams per data point.
     50 FRAMERATE_RECEIVED = 'framerate_received'
     51 # Max for all received streams per data point.
     52 FRAMERATE_RECEIVED_MAX = 'framerate_received_max'
     53 FRAMERATE_SENT = 'framerate_sent'
     54 GPU_PERCENT_OF_TOTAL = 'gpu_cpu_percent'
     55 LEAKY_BUCKET_DELAY = 'leaky_bucket_delay'
     56 NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS = 'num_active_vid_in_streams'
     57 RENDERER_CPU_PERCENT_OF_TOTAL = 'renderer_cpu_percent'
     58 SPEECH_EXPAND_RATE = 'speech_expand_rate'
     59 VIDEO_RECEIVED_FRAME_HEIGHT = 'video_received_frame_height'
     60 VIDEO_RECEIVED_FRAME_HEIGHT_MAX = 'video_received_frame_height_max'
     61 VIDEO_RECEIVED_FRAME_WIDTH = 'video_received_frame_width'
     62 VIDEO_RECEIVED_FRAME_WIDTH_MAX = 'video_received_frame_width_max'
     63 VIDEO_SENT_FRAME_HEIGHT = 'video_sent_frame_height'
     64 VIDEO_SENT_FRAME_WIDTH = 'video_sent_frame_width'
     65 
     66 
     67 # Mapping between metric names and how to extract the named metric using the
     68 # MediaInfoMetricsExtractor.
     69 METRIC_NAME_TO_EXTRACTOR_FUNC_DICT = {
     70     BROWSER_CPU_PERCENT_OF_TOTAL:
     71       lambda x: x.get_top_level_metric('browserProcessCpuUsage'),
     72     CPU_PERCENT_OF_TOTAL:
     73         lambda x: x.get_top_level_metric('systemcpuusage'),
     74     FRAMERATE_CAPTURED:
     75         lambda x: x.get_media_metric('fps',
     76                                    direction=DIRECTION.SENDER,
     77                                    media_type=MEDIA_TYPE.VIDEO),
     78     FRAMERATE_DECODED:
     79         lambda x: x.get_media_metric('fpsdecoded',
     80                                    direction=DIRECTION.RECEIVER,
     81                                    media_type=MEDIA_TYPE.VIDEO,
     82                                    post_process_func=_avg),
     83     FRAMERATE_DECODED_MAX:
     84         lambda x: x.get_media_metric('fpsdecoded',
     85                                    direction=DIRECTION.RECEIVER,
     86                                    media_type=MEDIA_TYPE.VIDEO,
     87                                    post_process_func=_max),
     88     FRAMERATE_RECEIVED:
     89         lambda x: x.get_media_metric('fpsnetwork',
     90                                    direction=DIRECTION.RECEIVER,
     91                                    media_type=MEDIA_TYPE.VIDEO,
     92                                    post_process_func=_avg),
     93     FRAMERATE_RECEIVED_MAX:
     94         lambda x: x.get_media_metric('fpsnetwork',
     95                                    direction=DIRECTION.RECEIVER,
     96                                    media_type=MEDIA_TYPE.VIDEO,
     97                                    post_process_func=_max),
     98     FRAMERATE_SENT:
     99         lambda x: x.get_media_metric('fpsnetwork',
    100                                    direction=DIRECTION.SENDER,
    101                                    media_type=MEDIA_TYPE.VIDEO),
    102     GPU_PERCENT_OF_TOTAL:
    103         lambda x: x.get_top_level_metric('gpuProcessCpuUsage'),
    104     LEAKY_BUCKET_DELAY:
    105         lambda x: x.get_media_metric('leakybucketdelay',
    106                                    direction=DIRECTION.BANDWIDTH_ESTIMATION),
    107     NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS:
    108         _get_number_of_incoming_active_video_streams,
    109     SPEECH_EXPAND_RATE:
    110         lambda x: x.get_media_metric('speechExpandRate',
    111                                    direction=DIRECTION.RECEIVER,
    112                                    media_type=MEDIA_TYPE.AUDIO,
    113                                    post_process_func=_avg),
    114     RENDERER_CPU_PERCENT_OF_TOTAL:
    115         lambda x: x.get_top_level_metric('processcpuusage'),
    116     VIDEO_RECEIVED_FRAME_WIDTH:
    117         lambda x: x.get_media_metric('width',
    118                                    direction=DIRECTION.RECEIVER,
    119                                    media_type=MEDIA_TYPE.VIDEO,
    120                                    post_process_func=_avg),
    121     VIDEO_RECEIVED_FRAME_WIDTH_MAX:
    122         lambda x: x.get_media_metric('width',
    123                                    direction=DIRECTION.RECEIVER,
    124                                    media_type=MEDIA_TYPE.VIDEO,
    125                                    post_process_func=_max),
    126     VIDEO_RECEIVED_FRAME_HEIGHT:
    127         lambda x: x.get_media_metric('height',
    128                                    direction=DIRECTION.RECEIVER,
    129                                    media_type=MEDIA_TYPE.VIDEO,
    130                                    post_process_func=_avg),
    131     VIDEO_RECEIVED_FRAME_HEIGHT_MAX:
    132         lambda x: x.get_media_metric('height',
    133                                    direction=DIRECTION.RECEIVER,
    134                                    media_type=MEDIA_TYPE.VIDEO,
    135                                    post_process_func=_max),
    136     VIDEO_SENT_FRAME_HEIGHT:
    137         lambda x: x.get_media_metric('height',
    138                                    direction=DIRECTION.SENDER,
    139                                    media_type=MEDIA_TYPE.VIDEO),
    140     VIDEO_SENT_FRAME_WIDTH:
    141         lambda x: x.get_media_metric('width',
    142                                    direction=DIRECTION.SENDER,
    143                                    media_type=MEDIA_TYPE.VIDEO),
    144 }
    145 
    146 class MetricsCollector(object):
    147     """Collects metrics for a test run."""
    148 
    149     def __init__(self, data_point_collector):
    150         """
    151         Initializes.
    152 
    153         @param data_point_collector
    154         """
    155         self._data_point_collector = data_point_collector
    156         self._extractor = None
    157 
    158     def collect_snapshot(self):
    159         """
    160         Stores new merics since the last call.
    161 
    162         Metrics can then be retrieved by calling get_metric.
    163         """
    164         self._data_point_collector.collect_snapshot()
    165         data_points = self._data_point_collector.get_data_points()
    166         # Replace the extractor on each snapshot to always support
    167         # getting metrics
    168         self._extractor = (media_info_metrics_extractor
    169                            .MediaInfoMetricsExtractor(data_points))
    170 
    171     def get_metric(self, name):
    172         """
    173         Gets the metric with the specified name.
    174 
    175         @param name The name of the metric
    176         @returns a list with (timestamp, value_list) tuples
    177         """
    178         if self._extractor is None:
    179             raise RuntimeError(
    180                     'collect_snapshot() must be called at least once.')
    181         return METRIC_NAME_TO_EXTRACTOR_FUNC_DICT[name](
    182                 self._extractor)
    183 
    184 
    185 class DataPointCollector(object):
    186     """Collects data points."""
    187 
    188     def __init__(self, cfm_facade):
    189         """
    190         Initializes.
    191 
    192         @param cfm_facade The cfm facade to use for getting data points.
    193         """
    194         self._cfm_facade = cfm_facade
    195         self._data_points = []
    196 
    197     def collect_snapshot(self):
    198         """
    199         Collects any new datapoints since the last collection.
    200         """
    201         data_points = self._cfm_facade.get_media_info_data_points()
    202         last_timestamp = (self._data_points[-1]['timestamp']
    203                           if self._data_points else 0)
    204         for data_point in data_points:
    205             if (data_point['timestamp'] >
    206                     last_timestamp + FLOATING_POINT_COMPARISON_DELTA):
    207                 self._data_points.append(data_point)
    208 
    209     def get_data_points(self):
    210         """
    211         Gets all collected data points.
    212         """
    213         return self._data_points
    214 
    215