import threading from autotest_lib.client.common_lib.cros import system_metrics_collector from autotest_lib.client.common_lib.cros.cfm.metrics import ( media_metrics_collector) class PerfMetricsCollector(object): """ Metrics collector that runs in seprate thread than the caller. """ def __init__(self, system_facade, cfm_facade, writer_function, additional_system_metrics=[]): """ Constructor. @param system_facade facade object to access system utils. @param cfm_facade facade object to access cfm utils. @param writer_function function called to collected metrics. @param additional_system_metrics Additional metrics to collect. """ metric_set = system_metrics_collector.create_default_metric_set( system_facade) for metric in additional_system_metrics: metric_set.append(metric) self._system_metrics_collector = ( system_metrics_collector.SystemMetricsCollector(system_facade, metric_set)) # Media metrics data_point_collector = media_metrics_collector.DataPointCollector( cfm_facade) self._media_metrics_collector = (media_metrics_collector .MetricsCollector(data_point_collector)) self._writer_function = writer_function # Collector thread. self._collector_thread = threading.Thread( target=self._collect_snapshots_until_stopped) self._stop = threading.Event() def start(self): """ Starts metrics collection. """ self._system_metrics_collector.pre_collect() self._collector_thread.start() def stop(self): """ Stops metrics collection. """ self._stop.set() def upload_metrics(self): """ Uploads collected metrics. """ self._upload_system_metrics() self._upload_media_metrics() def _collect_snapshots_until_stopped(self): while not self._stop.wait(10): self._system_metrics_collector.collect_snapshot() self._media_metrics_collector.collect_snapshot() def _upload_system_metrics(self): self._system_metrics_collector.write_metrics(self._writer_function) def _get_jmi_data(self, data_type): """ Gets jmi data for the given data type. @param data_type: Type of data to be retrieved from jmi data logs. @return Data for given data type from jmidata log. """ timestamped_values = self._media_metrics_collector.get_metric(data_type) # Strip timestamps. values = [x[1] for x in timestamped_values] # Each entry in values is a list, extract the raw values: res = [] for value_list in values: res.extend(value_list) # Ensure we always return at least one element, or perf uploads will # be sad. return res or [0] def _get_last_value(self, data_type): """ Gets last value of a list of numbers. @param data_type: Type of data to be retrieved from jmi data log. @return The last value in the jmidata for the specified data_type. 0 if there are no values in the jmidata for this data_type. """ data = self._get_jmi_data(data_type) if not data: return 0 return data[-1] def _upload_media_metrics(self): """ Write jmidata results to results-chart.json file for Perf Dashboard. """ # Video/Sender metrics self._writer_function( description='avg_encode_ms', value=self._get_jmi_data(media_metrics_collector.AVG_ENCODE_MS), units='ms', higher_is_better=False) self._writer_function( description='vid_out_frame_height', # video_out_res value=self._get_jmi_data(media_metrics_collector. VIDEO_SENT_FRAME_HEIGHT), units='px', higher_is_better=True) self._writer_function( description='vid_out_frame_width', value=self._get_jmi_data(media_metrics_collector. VIDEO_SENT_FRAME_WIDTH), units='px', higher_is_better=True) self._writer_function( description='vid_out_framerate_captured', value=self._get_jmi_data(media_metrics_collector. FRAMERATE_CAPTURED), units='fps', higher_is_better=True) self._writer_function( description='vid_out_framerate_encoded', value=self._get_jmi_data(media_metrics_collector. FRAMERATE_ENCODED), units='fps', higher_is_better=True) self._writer_function( description='vid_out_sent_packets', value=self._get_last_value(media_metrics_collector. VIDEO_SENT_PACKETS), units='packets', higher_is_better=True) # Video/Receiver metrics self._writer_function( description='vid_in_framerate_received', value=self._get_jmi_data(media_metrics_collector. FRAMERATE_NETWORK_RECEIVED), units='fps', higher_is_better=True) self._writer_function( description='vid_in_framerate_decoded', value=self._get_jmi_data(media_metrics_collector.FRAMERATE_DECODED), units='fps', higher_is_better=True) self._writer_function( description='vid_in_framerate_to_renderer', value=self._get_jmi_data(media_metrics_collector. FRAMERATE_TO_RENDERER), units='fps', higher_is_better=True) self._writer_function( description='video_in_frame_heigth', # video_in_res value=self._get_jmi_data(media_metrics_collector. VIDEO_RECEIVED_FRAME_HEIGHT), units='px', higher_is_better=True) self._writer_function( description='vid_in_frame_width', value=self._get_jmi_data(media_metrics_collector. VIDEO_RECEIVED_FRAME_WIDTH), units='px', higher_is_better=True) # Adaptation metrics self._writer_function( description='vid_out_adapt_changes', value=self._get_last_value(media_metrics_collector. ADAPTATION_CHANGES), units='count', higher_is_better=False) self._writer_function( description='vid_out_adapt_reasons', value=self._get_jmi_data(media_metrics_collector.ADAPTATION_REASON), units='reasons', higher_is_better=False) # System metrics self._writer_function( description='cpu_usage_jmi', value=self._get_jmi_data(media_metrics_collector. CPU_PERCENT_OF_TOTAL), units='percent', higher_is_better=False) self._writer_function( description='process_js_memory', value=[(x / (1024 * 1024)) for x in self._get_jmi_data( media_metrics_collector.PROCESS_JS_MEMORY_USED)], units='MB', higher_is_better=False) self._writer_function( description='renderer_cpu_usage', value=self._get_jmi_data( media_metrics_collector.RENDERER_CPU_PERCENT_OF_TOTAL), units='percent', higher_is_better=False) self._writer_function( description='browser_cpu_usage', value=self._get_jmi_data( media_metrics_collector.BROWSER_CPU_PERCENT_OF_TOTAL), units='percent', higher_is_better=False) self._writer_function( description='gpu_cpu_usage', value=self._get_jmi_data( media_metrics_collector.GPU_PERCENT_OF_TOTAL), units='percent', higher_is_better=False) # Other self._writer_function( description='active_streams', value=self._get_jmi_data(media_metrics_collector. NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS), units='count', higher_is_better=True)