Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Side by Side Diff: build/android/pylib/device/logcat_monitor.py

Issue 896503002: [Android] Add LogcatMonitor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 # found in the LICENSE file.
4
5 # pylint: disable=unused-argument
6
7 import collections
8 import itertools
9 import logging
10 import subprocess
11 import tempfile
12 import time
13 import re
14
15 from pylib.device import adb_wrapper
16 from pylib.device import decorators
17 from pylib.device import device_errors
18
19
20 class LogcatMonitor(object):
21
22 # Format: <DATE> <TIME> <PID> <TID> <LEVEL> <COMPONENT>: <MESSAGE>
23 _THREADTIME_RE_FORMAT = r'\S* +\S* +(%s) +(%s) +(%s) +(%s): +(%s)$'
24
25 def __init__(self, adb, clear=True, filters=None):
26 if isinstance(adb, adb_wrapper.AdbWrapper):
27 self._adb = adb
28 else:
29 raise ValueError('Unsupported type passed for argument "device"')
30 self._clear = clear
31 self._filters = filters
32 self._logcat_out = None
33 self._logcat_out_file = None
34 self._logcat_proc = None
35
36 @decorators.WithTimeoutAndRetriesDefaults(10, 0)
37 def WaitFor(self, success_regex, failure_regex, timeout=None, retries=None):
38 """Waits for a logcat line matching the provided regular expression.
klundberg 2015/02/02 20:00:40 As discussed offline, it might be good to update t
jbudorick 2015/02/02 21:47:38 Clarified the docstring and added an implementatio
39
40 Note that this calls re.search on each logcat line, not re.match, so the
41 provided regular expressions don't have to match an entire line.
42
43 Args:
44 success_regex: The regular expression to search for.
45 failure_regex: An optional regular expression that, if hit, causes this
46 to stop looking for a match. Can be None.
47 timeout: timeout in seconds
48 retries: number of retries
49
50 Returns:
51 A match object if |success_regex| matches a part of a logcat line, or
52 None if |failure_regex| matches a part of a logcat line.
53 Raises:
54 CommandFailedError on logcat failure (NOT on a |failure_regex| match)
klundberg 2015/02/02 20:00:40 minor nit: perioad at the end of the sentence.
jbudorick 2015/02/02 21:47:38 Done.
55 CommandTimeoutError if a logcat line matching |success_regex| is not
56 found in |timeout| seconds.
57 DeviceUnreachableError if the device becomes unreachable.
58 """
59 if isinstance(success_regex, basestring):
60 success_regex = re.compile(success_regex)
61 if isinstance(failure_regex, basestring):
62 failure_regex = re.compile(failure_regex)
63
64 logging.debug('Waiting %d seconds for "%s"', timeout, success_regex.pattern)
65
66 for l in self._adb.Logcat():
67 m = success_regex.search(l)
68 if m:
69 return m
70 if failure_regex and failure_regex.search(l):
71 return None
72
73 def FindAll(self, message_regex, proc_id=None, thread_id=None, log_level=None,
74 component=None):
75 """Finds all lines in the logcat that match the provided constraints.
76
77 Args:
78 message_regex: The regular expression that the <message> section must
79 match.
80 proc_id: The process ID to match. If None, matches any process ID.
81 thread_id: The thread ID to match. If None, matches any thread ID.
82 log_level: The log level to match. If None, matches any log level.
83 component: The component to match. If None, matches any component.
84
85 Returns:
86 An iterable containing objects with five attributes:
87 |proc_id|: the process ID
88 |thread_id|: the thread ID
89 |log_level|: the log level
90 |component|: the component
91 |message|: the logcat message
92 """
93 LogcatLine = collections.namedtuple(
94 'LogcatLine',
95 ['proc_id', 'thread_id', 'log_level', 'component', 'message'])
96
97 if proc_id is None:
98 proc_id = r'\d+'
99 if thread_id is None:
100 thread_id = r'\d+'
101 if log_level is None:
102 log_level = r'[VDIWEF]'
103 if component is None:
104 component = r'[^\s:]+'
105 threadtime_re = re.compile(
106 type(self)._THREADTIME_RE_FORMAT % (
107 proc_id, thread_id, log_level, component, message_regex))
108
109 regexed_lines = (
110 re.match(threadtime_re, l)
111 for l in self._adb.Logcat(dump=True, logcat_format='threadtime'))
112 only_matches = (m for m in regexed_lines if m)
113 return (LogcatLine(*m.group(1, 2, 3, 4, 5)) for m in only_matches)
114
115 def Start(self):
116 """Starts the logcat monitor."""
117 if self._clear:
118 self._adb.Logcat(clear=True)
119
120 def Stop(self):
121 """Stops the logcat monitor."""
122 pass
123
124 def __enter__(self):
125 """Starts the logcat monitor."""
126 self.Start()
127 return self
128
129 def __exit__(self, exc_type, exc_val, exc_tb):
130 """Stops the logcat monitor."""
131 self.Stop()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698