• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import threading
2
3from autotest_lib.client.common_lib.cros import system_metrics_collector
4from autotest_lib.client.common_lib.cros.cfm.metrics import (
5        media_metrics_collector)
6
7
8class PerfMetricsCollector(object):
9    """
10    Metrics collector that runs in seprate thread than the caller.
11    """
12    def __init__(self, system_facade, cfm_facade, writer_function,
13                 additional_system_metrics=[]):
14        """
15        Constructor.
16
17        @param system_facade facade object to access system utils.
18        @param cfm_facade facade object to access cfm utils.
19        @param writer_function function called to collected metrics.
20        @param additional_system_metrics Additional metrics to collect.
21        """
22        metric_set = system_metrics_collector.create_default_metric_set(
23            system_facade)
24        for metric in additional_system_metrics:
25            metric_set.append(metric)
26        self._system_metrics_collector = (
27            system_metrics_collector.SystemMetricsCollector(system_facade,
28                                                            metric_set))
29        # Media metrics
30        data_point_collector = media_metrics_collector.DataPointCollector(
31            cfm_facade)
32        self._media_metrics_collector = (media_metrics_collector
33                                        .MetricsCollector(data_point_collector))
34
35        self._writer_function = writer_function
36        # Collector thread.
37        self._collector_thread = threading.Thread(
38            target=self._collect_snapshots_until_stopped)
39        self._stop = threading.Event()
40
41    def start(self):
42        """
43        Starts metrics collection.
44        """
45        self._system_metrics_collector.pre_collect()
46        self._collector_thread.start()
47
48    def stop(self):
49        """
50        Stops metrics collection.
51        """
52        self._stop.set()
53        self._system_metrics_collector.post_collect()
54
55    def upload_metrics(self):
56        """
57        Uploads collected metrics.
58        """
59        self._upload_system_metrics()
60        self._upload_media_metrics()
61
62    def _collect_snapshots_until_stopped(self):
63        while not self._stop.wait(10):
64            self._system_metrics_collector.collect_snapshot()
65            self._media_metrics_collector.collect_snapshot()
66
67    def _upload_system_metrics(self):
68        self._system_metrics_collector.write_metrics(self._writer_function)
69
70    def _get_jmi_data(self, data_type):
71        """
72        Gets jmi data for the given data type.
73
74        @param data_type: Type of data to be retrieved from jmi data logs.
75        @return Data for given data type from jmidata log.
76        """
77        timestamped_values = self._media_metrics_collector.get_metric(data_type)
78        # Strip timestamps.
79        values = [x[1] for x in timestamped_values]
80        # Each entry in values is a list, extract the raw values:
81        res = []
82        for value_list in values:
83            res.extend(value_list)
84        # Ensure we always return at least one element, or perf uploads will
85        # be sad.
86        return res or [0]
87
88    def _get_last_value(self, data_type):
89        """
90        Gets last value of a list of numbers.
91
92        @param data_type: Type of data to be retrieved from jmi data log.
93        @return The last value in the jmidata for the specified data_type. 0 if
94                there are no values in the jmidata for this data_type.
95        """
96        data = self._get_jmi_data(data_type)
97        if not data:
98            return 0
99        return data[-1]
100
101    def _upload_media_metrics(self):
102        """
103        Write jmidata results to results-chart.json file for Perf Dashboard.
104        """
105        # Video/Sender metrics
106        self._writer_function(
107            description='avg_encode_ms',
108            value=self._get_jmi_data(media_metrics_collector.AVG_ENCODE_MS),
109            units='ms',
110            higher_is_better=False)
111
112        self._writer_function(
113            description='vid_out_frame_height', # video_out_res
114            value=self._get_jmi_data(media_metrics_collector.
115                VIDEO_SENT_FRAME_HEIGHT),
116            units='px',
117            higher_is_better=True)
118
119        self._writer_function(
120            description='vid_out_frame_width',
121            value=self._get_jmi_data(media_metrics_collector.
122                VIDEO_SENT_FRAME_WIDTH),
123            units='px',
124            higher_is_better=True)
125
126        self._writer_function(
127            description='vid_out_framerate_captured',
128            value=self._get_jmi_data(media_metrics_collector.
129                FRAMERATE_CAPTURED),
130            units='fps',
131            higher_is_better=True)
132
133        self._writer_function(
134            description='vid_out_framerate_encoded',
135            value=self._get_jmi_data(media_metrics_collector.
136                FRAMERATE_ENCODED),
137            units='fps',
138            higher_is_better=True)
139
140        self._writer_function(
141            description='vid_out_sent_packets',
142            value=self._get_last_value(media_metrics_collector.
143                VIDEO_SENT_PACKETS),
144            units='packets',
145            higher_is_better=True)
146
147        # Video/Receiver metrics
148        self._writer_function(
149            description='vid_in_framerate_received',
150            value=self._get_jmi_data(media_metrics_collector.
151                FRAMERATE_NETWORK_RECEIVED),
152            units='fps',
153            higher_is_better=True)
154
155        self._writer_function(
156            description='vid_in_framerate_decoded',
157            value=self._get_jmi_data(media_metrics_collector.FRAMERATE_DECODED),
158            units='fps',
159            higher_is_better=True)
160
161        self._writer_function(
162            description='vid_in_framerate_to_renderer',
163            value=self._get_jmi_data(media_metrics_collector.
164                FRAMERATE_TO_RENDERER),
165            units='fps',
166            higher_is_better=True)
167
168        self._writer_function(
169            description='video_in_frame_heigth', # video_in_res
170            value=self._get_jmi_data(media_metrics_collector.
171                VIDEO_RECEIVED_FRAME_HEIGHT),
172            units='px',
173            higher_is_better=True)
174
175        self._writer_function(
176            description='vid_in_frame_width',
177            value=self._get_jmi_data(media_metrics_collector.
178                VIDEO_RECEIVED_FRAME_WIDTH),
179            units='px',
180            higher_is_better=True)
181
182        # Adaptation metrics
183        self._writer_function(
184            description='vid_out_adapt_changes',
185            value=self._get_last_value(media_metrics_collector.
186                ADAPTATION_CHANGES),
187            units='count',
188            higher_is_better=False)
189
190        self._writer_function(
191            description='vid_out_adapt_reasons',
192            value=self._get_jmi_data(media_metrics_collector.ADAPTATION_REASON),
193            units='reasons',
194            higher_is_better=False)
195
196        # System metrics
197        self._writer_function(
198            description='cpu_usage_jmi',
199            value=self._get_jmi_data(media_metrics_collector.
200                CPU_PERCENT_OF_TOTAL),
201            units='percent',
202            higher_is_better=False)
203
204        self._writer_function(
205            description='process_js_memory',
206            value=[(x / (1024 * 1024)) for x in self._get_jmi_data(
207                media_metrics_collector.PROCESS_JS_MEMORY_USED)],
208            units='MB',
209            higher_is_better=False)
210
211        self._writer_function(
212            description='renderer_cpu_usage',
213            value=self._get_jmi_data(
214                media_metrics_collector.RENDERER_CPU_PERCENT_OF_TOTAL),
215            units='percent',
216            higher_is_better=False)
217
218        self._writer_function(
219            description='browser_cpu_usage',
220            value=self._get_jmi_data(
221                media_metrics_collector.BROWSER_CPU_PERCENT_OF_TOTAL),
222            units='percent',
223            higher_is_better=False)
224
225        self._writer_function(
226            description='gpu_cpu_usage',
227            value=self._get_jmi_data(
228                media_metrics_collector.GPU_PERCENT_OF_TOTAL),
229            units='percent',
230            higher_is_better=False)
231
232        # Other
233        self._writer_function(
234            description='active_streams',
235            value=self._get_jmi_data(media_metrics_collector.
236                NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS),
237            units='count',
238            higher_is_better=True)
239