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 |