Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 28 additions & 25 deletions pidcat.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
parser.add_argument('-t', '--tag', dest='tag', action='append', help='Filter output by specified tag(s)')
parser.add_argument('-i', '--ignore-tag', dest='ignored_tag', action='append', help='Filter output by ignoring specified tag(s)')
parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + __version__, help='Print the version number and exit')
parser.add_argument('--time', dest='time', action='store_true', default=False, help='Print time')
parser.add_argument('-a', '--all', dest='all', action='store_true', default=False, help='Print all log messages')

args = parser.parse_args()
Expand Down Expand Up @@ -76,7 +77,7 @@
# Convert default process names from <package>: (cli notation) to <package> (android notation) in the exact names match group.
named_processes = map(lambda package: package if package.find(":") != len(package) - 1 else package[:-1], named_processes)

header_size = args.tag_width + 1 + 3 + 1 # space, level, space
header_size = args.tag_width + 1 + 3 + 1 + (18 if args.time else 0) # space, level, space

width = -1
try:
Expand Down Expand Up @@ -164,20 +165,21 @@ def allocate_color(tag):
'F': colorize(' F ', fg=BLACK, bg=RED),
}

PID_LINE = re.compile(r'^\w+\s+(\w+)\s+\w+\s+\w+\s+\w+\s+\w+\s+\w+\s+\w\s([\w|\.|\/]+)$')
PID_START = re.compile(r'^.*: Start proc ([a-zA-Z0-9._:]+) for ([a-z]+ [^:]+): pid=(\d+) uid=(\d+) gids=(.*)$')
PID_START_5_1 = re.compile(r'^.*: Start proc (\d+):([a-zA-Z0-9._:]+)/[a-z0-9]+ for (.*)$')
PID_START_DALVIK = re.compile(r'^E/dalvikvm\(\s*(\d+)\): >>>>> ([a-zA-Z0-9._:]+) \[ userId:0 \| appId:(\d+) \]$')
PID_KILL = re.compile(r'^Killing (\d+):([a-zA-Z0-9._:]+)/[^:]+: (.*)$')
PID_LEAVE = re.compile(r'^No longer want ([a-zA-Z0-9._:]+) \(pid (\d+)\): .*$')
PID_DEATH = re.compile(r'^Process ([a-zA-Z0-9._:]+) \(pid (\d+)\) has died.?$')
LOG_LINE = re.compile(r'^([A-Z])/(.+?)\( *(\d+)\): (.*?)$')
BUG_LINE = re.compile(r'.*nativeGetEnabledTags.*')
BACKTRACE_LINE = re.compile(r'^#(.*?)pc\s(.*?)$')
TIME_FORMAT = r'^(\d+-\d+\s+\d+:\d+:\d+\.\d+\s+)?'
PID_LINE = re.compile(TIME_FORMAT+r'\w+\s+(\w+)\s+\w+\s+\w+\s+\w+\s+\w+\s+\w+\s+\w\s([\w|\.|\/]+)$')
PID_START = re.compile(TIME_FORMAT+r'.*: Start proc ([a-zA-Z0-9._:]+) for ([a-z]+ [^:]+): pid=(\d+) uid=(\d+) gids=(.*)$')
PID_START_5_1 = re.compile(TIME_FORMAT+r'.*: Start proc (\d+):([a-zA-Z0-9._:]+)/[a-z0-9]+ for (.*)$')
PID_START_DALVIK = re.compile(TIME_FORMAT+r'E/dalvikvm\(\s*(\d+)\): >>>>> ([a-zA-Z0-9._:]+) \[ userId:0 \| appId:(\d+) \]$')
PID_KILL = re.compile(TIME_FORMAT+r'Killing (\d+):([a-zA-Z0-9._:]+)/[^:]+: (.*)$')
PID_LEAVE = re.compile(TIME_FORMAT+r'No longer want ([a-zA-Z0-9._:]+) \(pid (\d+)\): .*$')
PID_DEATH = re.compile(TIME_FORMAT+r'Process ([a-zA-Z0-9._:]+) \(pid (\d+)\) has died.?$')
LOG_LINE = re.compile(TIME_FORMAT+r'([A-Z])/(.+?)\( *(\d+)\): (.*?)$')
BUG_LINE = re.compile(TIME_FORMAT+r'.*nativeGetEnabledTags.*')
BACKTRACE_LINE = re.compile(TIME_FORMAT+r'#(.*?)pc\s(.*?)$')

adb_command = base_adb_command[:]
adb_command.append('logcat')
adb_command.extend(['-v', 'brief'])
adb_command.extend(['-v', 'time'])

# Clear log before starting logcat
if args.clear_logcat:
Expand Down Expand Up @@ -216,36 +218,36 @@ def parse_death(tag, message):
return None, None
kill = PID_KILL.match(message)
if kill:
pid = kill.group(1)
package_line = kill.group(2)
pid = kill.group(2)
package_line = kill.group(3)
if match_packages(package_line) and pid in pids:
return pid, package_line
leave = PID_LEAVE.match(message)
if leave:
pid = leave.group(2)
package_line = leave.group(1)
pid = leave.group(3)
package_line = leave.group(2)
if match_packages(package_line) and pid in pids:
return pid, package_line
death = PID_DEATH.match(message)
if death:
pid = death.group(2)
package_line = death.group(1)
pid = death.group(3)
package_line = death.group(2)
if match_packages(package_line) and pid in pids:
return pid, package_line
return None, None

def parse_start_proc(line):
start = PID_START_5_1.match(line)
if start is not None:
line_pid, line_package, target = start.groups()
line_time, line_pid, line_package, target = start.groups()
return line_package, target, line_pid, '', ''
start = PID_START.match(line)
if start is not None:
line_package, target, line_pid, line_uid, line_gids = start.groups()
line_time, line_package, target, line_pid, line_uid, line_gids = start.groups()
return line_package, target, line_pid, line_uid, line_gids
start = PID_START_DALVIK.match(line)
if start is not None:
line_pid, line_package, line_uid = start.groups()
line_time, line_pid, line_package, line_uid = start.groups()
return line_package, '', line_pid, line_uid, ''
return None

Expand All @@ -264,8 +266,8 @@ def tag_in_tags_regex(tag, tags):

pid_match = PID_LINE.match(line)
if pid_match is not None:
pid = pid_match.group(1)
proc = pid_match.group(2)
pid = pid_match.group(2)
proc = pid_match.group(3)
if proc in catchall_package:
seen_pids = True
pids.add(pid)
Expand All @@ -286,7 +288,7 @@ def tag_in_tags_regex(tag, tags):
if log_line is None:
continue

level, tag, owner, message = log_line.groups()
line_time, level, tag, owner, message = log_line.groups()
tag = tag.strip()
start = parse_start_proc(line)
if start:
Expand All @@ -297,6 +299,7 @@ def tag_in_tags_regex(tag, tags):
app_pid = line_pid

linebuf = '\n'
linebuf += line_time if args.time and line_time != None else ''
linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
linebuf += indent_wrap(' Process %s created for %s\n' % (line_package, target))
linebuf += colorize(' ' * (header_size - 1), bg=WHITE)
Expand Down Expand Up @@ -331,7 +334,7 @@ def tag_in_tags_regex(tag, tags):
if args.tag and not tag_in_tags_regex(tag, args.tag):
continue

linebuf = ''
linebuf = line_time if args.time and line_time != None else ''

# right-align tag title and allocate color if needed
if tag != last_tag or args.always_tags:
Expand Down
1 change: 1 addition & 0 deletions zsh-completion/_pidcat
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ _pidcat() {
'-l[Minimum level to be displayed]: :_pidcat_log_levels' \
'-a[Print all log messages]' \
'--color-gc[Color garbage collection]' \
'--time[Print time]' \
'--always-display-tags[Always display the tag name]' \
'--current[Filter logcat by current running app]' \
'*:: :_pidcat_processes' \
Expand Down