Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Monitor tracing events on chrome via chrome remote debugging.""" | 5 """Monitor tracing events on chrome via chrome remote debugging.""" |
| 6 | 6 |
| 7 import bisect | 7 import bisect |
| 8 import itertools | 8 import itertools |
| 9 | 9 |
| 10 import devtools_monitor | 10 import devtools_monitor |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 Args: | 21 Args: |
| 22 connection: a DevToolsConnection. | 22 connection: a DevToolsConnection. |
| 23 categories: None, or a string, or list of strings, of tracing categories | 23 categories: None, or a string, or list of strings, of tracing categories |
| 24 to filter. | 24 to filter. |
| 25 | 25 |
| 26 fetch_stream: if true, use a websocket stream to fetch tracing data rather | 26 fetch_stream: if true, use a websocket stream to fetch tracing data rather |
| 27 than dataCollected events. It appears based on very limited testing that | 27 than dataCollected events. It appears based on very limited testing that |
| 28 a stream is slower than the default reporting as dataCollected events. | 28 a stream is slower than the default reporting as dataCollected events. |
| 29 """ | 29 """ |
| 30 super(TracingTrack, self).__init__(connection) | 30 super(TracingTrack, self).__init__(connection) |
| 31 connection.RegisterListener('Tracing.dataCollected', self) | 31 if connection: |
|
mattcary
2016/01/19 15:24:47
Generally I try to minimize testing-specific tweak
Benoit L
2016/01/19 15:54:50
I agree. But in this instance this is not for test
| |
| 32 connection.RegisterListener('Tracing.dataCollected', self) | |
| 32 params = {} | 33 params = {} |
| 33 if categories: | 34 if categories: |
| 34 params['categories'] = (categories if type(categories) is str | 35 params['categories'] = (categories if type(categories) is str |
| 35 else ','.join(categories)) | 36 else ','.join(categories)) |
| 36 if fetch_stream: | 37 if fetch_stream: |
| 37 params['transferMode'] = 'ReturnAsStream' | 38 params['transferMode'] = 'ReturnAsStream' |
| 38 | 39 |
| 39 connection.SyncRequestNoResponse('Tracing.start', params) | 40 if connection: |
| 41 connection.SyncRequestNoResponse('Tracing.start', params) | |
| 40 self._events = [] | 42 self._events = [] |
| 41 | 43 |
| 42 self._event_msec_index = None | 44 self._event_msec_index = None |
| 43 self._event_lists = None | 45 self._event_lists = None |
| 44 | 46 |
| 45 def Handle(self, method, event): | 47 def Handle(self, method, event): |
| 46 for e in event['params']['value']: | 48 for e in event['params']['value']: |
| 47 self._events.append(Event(e)) | 49 self._events.append(Event(e)) |
| 48 # Just invalidate our indices rather than trying to be fancy and | 50 # Just invalidate our indices rather than trying to be fancy and |
| 49 # incrementally update. | 51 # incrementally update. |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 69 self._IndexEvents() | 71 self._IndexEvents() |
| 70 idx = bisect.bisect_right(self._event_msec_index, msec) - 1 | 72 idx = bisect.bisect_right(self._event_msec_index, msec) - 1 |
| 71 if idx < 0: | 73 if idx < 0: |
| 72 return [] | 74 return [] |
| 73 events = self._event_lists[idx] | 75 events = self._event_lists[idx] |
| 74 assert events.start_msec <= msec | 76 assert events.start_msec <= msec |
| 75 if not events or events.end_msec < msec: | 77 if not events or events.end_msec < msec: |
| 76 return [] | 78 return [] |
| 77 return events.event_list | 79 return events.event_list |
| 78 | 80 |
| 81 | |
| 82 def ToJsonDict(self): | |
| 83 return {'events': [e.ToJsonDict() for e in self._events]} | |
| 84 | |
| 85 @classmethod | |
| 86 def FromJsonDict(cls, json_dict): | |
| 87 assert 'events' in json_dict | |
| 88 events = [Event(e) for e in json_dict['events']] | |
| 89 tracing_track = TracingTrack(None) | |
| 90 tracing_track._events = events | |
| 91 return tracing_track | |
| 92 | |
| 79 def _IndexEvents(self): | 93 def _IndexEvents(self): |
| 80 """Computes index for in-flight events. | 94 """Computes index for in-flight events. |
| 81 | 95 |
| 82 Creates a list of timestamps where events start or end, and tracks the | 96 Creates a list of timestamps where events start or end, and tracks the |
| 83 current set of in-flight events at the instant after each timestamp. To do | 97 current set of in-flight events at the instant after each timestamp. To do |
| 84 this we have to synthesize ending events for complete events, as well as | 98 this we have to synthesize ending events for complete events, as well as |
| 85 join and track the nesting of async, flow and other spanning events. | 99 join and track the nesting of async, flow and other spanning events. |
| 86 | 100 |
| 87 Events such as instant and counter events that aren't indexable are skipped. | 101 Events such as instant and counter events that aren't indexable are skipped. |
| 88 | 102 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 268 if not synthetic and tracing_event['ph'] in ['p']: | 282 if not synthetic and tracing_event['ph'] in ['p']: |
| 269 raise devtools_monitor.DevToolsConnectionException( | 283 raise devtools_monitor.DevToolsConnectionException( |
| 270 'Deprecated event: %s' % tracing_event) | 284 'Deprecated event: %s' % tracing_event) |
| 271 | 285 |
| 272 self._tracing_event = tracing_event | 286 self._tracing_event = tracing_event |
| 273 # Note tracing event times are in microseconds. | 287 # Note tracing event times are in microseconds. |
| 274 self._start_msec = tracing_event['ts'] / 1000.0 | 288 self._start_msec = tracing_event['ts'] / 1000.0 |
| 275 self._end_msec = None | 289 self._end_msec = None |
| 276 self._synthetic = synthetic | 290 self._synthetic = synthetic |
| 277 if self.type == 'X': | 291 if self.type == 'X': |
| 278 self._end_msec = self.start_msec + tracing_event['dur'] / 1000.0 | 292 # Some events don't have a duration. |
| 293 duration = (tracing_event['dur'] | |
| 294 if 'dur' in tracing_event else tracing_event['tdur']) | |
| 295 self._end_msec = self.start_msec + duration / 1000.0 | |
| 279 | 296 |
| 280 @property | 297 @property |
| 281 def start_msec(self): | 298 def start_msec(self): |
| 282 return self._start_msec | 299 return self._start_msec |
| 283 | 300 |
| 284 @property | 301 @property |
| 285 def end_msec(self): | 302 def end_msec(self): |
| 286 return self._end_msec | 303 return self._end_msec |
| 287 | 304 |
| 288 @property | 305 @property |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 'Bad closing: %s --> %s' % (self, closing)) | 366 'Bad closing: %s --> %s' % (self, closing)) |
| 350 if self.type in ['b', 'S'] and ( | 367 if self.type in ['b', 'S'] and ( |
| 351 self.tracing_event['cat'] != closing.tracing_event['cat'] or | 368 self.tracing_event['cat'] != closing.tracing_event['cat'] or |
| 352 self.id != closing.id): | 369 self.id != closing.id): |
| 353 raise devtools_monitor.DevToolsConnectionException( | 370 raise devtools_monitor.DevToolsConnectionException( |
| 354 'Bad async closing: %s --> %s' % (self, closing)) | 371 'Bad async closing: %s --> %s' % (self, closing)) |
| 355 self._end_msec = closing.start_msec | 372 self._end_msec = closing.start_msec |
| 356 if 'args' in closing.tracing_event: | 373 if 'args' in closing.tracing_event: |
| 357 self.tracing_event.setdefault( | 374 self.tracing_event.setdefault( |
| 358 'args', {}).update(closing.tracing_event['args']) | 375 'args', {}).update(closing.tracing_event['args']) |
| 376 | |
| 377 def ToJsonDict(self): | |
| 378 return self._tracing_event | |
| 379 | |
| 380 @classmethod | |
| 381 def FromJsonDict(cls, json_dict): | |
| 382 return Event(json_dict) | |
| OLD | NEW |