Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 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 # pylint: disable=unused-argument | 5 # pylint: disable=unused-argument |
| 6 | 6 |
| 7 import logging | 7 import logging |
| 8 import os | 8 import os |
| 9 import re | 9 import re |
| 10 import shutil | 10 import shutil |
| 11 import tempfile | 11 import tempfile |
| 12 import threading | 12 import threading |
| 13 import time | 13 import time |
| 14 | 14 |
| 15 from devil.android import decorators | 15 from devil.android import decorators |
| 16 from devil.android import device_errors | 16 from devil.android import device_errors |
| 17 from devil.android.sdk import adb_wrapper | 17 from devil.android.sdk import adb_wrapper |
| 18 from devil.utils import reraiser_thread | 18 from devil.utils import reraiser_thread |
| 19 | 19 |
| 20 | 20 |
| 21 class LogcatMonitor(object): | 21 class LogcatMonitor(object): |
| 22 | 22 |
| 23 _LOGCAT_GENERATOR_TIMEOUT = 5.0 | |
| 23 _WAIT_TIME = 0.2 | 24 _WAIT_TIME = 0.2 |
| 24 _THREADTIME_RE_FORMAT = ( | 25 _THREADTIME_RE_FORMAT = ( |
| 25 r'(?P<date>\S*) +(?P<time>\S*) +(?P<proc_id>%s) +(?P<thread_id>%s) +' | 26 r'(?P<date>\S*) +(?P<time>\S*) +(?P<proc_id>%s) +(?P<thread_id>%s) +' |
| 26 r'(?P<log_level>%s) +(?P<component>%s) *: +(?P<message>%s)$') | 27 r'(?P<log_level>%s) +(?P<component>%s) *: +(?P<message>%s)$') |
| 27 | 28 |
| 28 def __init__(self, adb, clear=True, filter_specs=None, output_file=None): | 29 def __init__(self, adb, clear=True, filter_specs=None, output_file=None): |
| 29 """Create a LogcatMonitor instance. | 30 """Create a LogcatMonitor instance. |
| 30 | 31 |
| 31 Args: | 32 Args: |
| 32 adb: An instance of adb_wrapper.AdbWrapper. | 33 adb: An instance of adb_wrapper.AdbWrapper. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 | 148 |
| 148 def _StartRecording(self): | 149 def _StartRecording(self): |
| 149 """Starts recording logcat to file. | 150 """Starts recording logcat to file. |
| 150 | 151 |
| 151 Function spawns a thread that records logcat to file and will not die | 152 Function spawns a thread that records logcat to file and will not die |
| 152 until |StopRecording| is called. | 153 until |StopRecording| is called. |
| 153 """ | 154 """ |
| 154 def record_to_file(): | 155 def record_to_file(): |
| 155 # Write the log with line buffering so the consumer sees each individual | 156 # Write the log with line buffering so the consumer sees each individual |
| 156 # line. | 157 # line. |
| 158 logcat_generator = self._adb.Logcat(filter_specs=self._filter_specs, | |
| 159 logcat_format='threadtime') | |
| 160 @decorators.WithExplicitTimeoutAndRetries( | |
|
jbudorick
2016/01/26 23:13:19
This decorator is here to check a condition (wheth
jbudorick
2016/01/26 23:32:37
As for the slowness part, we could potentially add
| |
| 161 self._LOGCAT_GENERATOR_TIMEOUT, 0) | |
| 162 def logcat_next(): | |
| 163 logcat_generator.next() | |
| 164 | |
| 157 with open(self._record_file.name, 'a', 1) as f: | 165 with open(self._record_file.name, 'a', 1) as f: |
| 158 for data in self._adb.Logcat(filter_specs=self._filter_specs, | 166 while True: |
| 159 logcat_format='threadtime'): | 167 try: |
| 168 data = logcat_next() | |
| 169 f.write(data + '\n') | |
| 170 except device_errors.CommandTimeoutError: | |
| 171 pass | |
| 160 if self._stop_recording_event.isSet(): | 172 if self._stop_recording_event.isSet(): |
| 161 f.flush() | 173 f.flush() |
| 162 return | 174 return |
| 163 f.write(data + '\n') | |
| 164 | 175 |
| 165 self._stop_recording_event.clear() | 176 self._stop_recording_event.clear() |
| 166 if not self._record_thread: | 177 if not self._record_thread: |
| 167 self._record_thread = reraiser_thread.ReraiserThread(record_to_file) | 178 self._record_thread = reraiser_thread.ReraiserThread(record_to_file) |
| 168 self._record_thread.start() | 179 self._record_thread.start() |
| 169 | 180 |
| 170 def _StopRecording(self): | 181 def _StopRecording(self): |
| 171 """Finish recording logcat.""" | 182 """Finish recording logcat.""" |
| 172 if self._record_thread: | 183 if self._record_thread: |
| 173 self._stop_recording_event.set() | 184 self._stop_recording_event.set() |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 def __del__(self): | 229 def __del__(self): |
| 219 """Closes logcat recording file in case |Close| was never called.""" | 230 """Closes logcat recording file in case |Close| was never called.""" |
| 220 if self._record_file: | 231 if self._record_file: |
| 221 logging.warning('Need to call |Close| on the logcat monitor when done!') | 232 logging.warning('Need to call |Close| on the logcat monitor when done!') |
| 222 self._record_file.close() | 233 self._record_file.close() |
| 223 | 234 |
| 224 | 235 |
| 225 class LogcatMonitorCommandError(device_errors.CommandFailedError): | 236 class LogcatMonitorCommandError(device_errors.CommandFailedError): |
| 226 """Exception for errors with logcat monitor commands.""" | 237 """Exception for errors with logcat monitor commands.""" |
| 227 pass | 238 pass |
| OLD | NEW |