Wai Hon's Blog

More Effective ADB Logcat

2022-06-12 #engineering #android

Our team works on Android and uses adb logcat a lot. I have heard coworkers complaining about how spammy the logs are and why some logs are missing from the output of adb logcat.

Most of us, including me, start with piping the output to grep for filtering, (i.e., adb logcat | grep <pattern>). This is intuitive for command-line users. This works in practice but there are downsides if it is the only way to do Android logging (i.e., not using tag and priority.)

Trick 0: Set the Minimum Log Priority for Tag

The first downside of not using tags and priorities is that code writers tend to print all logs to at least the default priority, Debug (D). This is because they cannot see the lowest priority Verbose (V) logs from adb logcat. As a result, some logs that should be used in debugging a specific class are printed all the time, spamming everyone.

The second downside is not knowing how to see the Verbose (V) log. For a log to appear in adb logcat, its log priority needs to be at least the minimum log priority set for its tag. For example, the following code will make all logs with the tag tag1 appear in adb logcat:

# Set the minimum log priority to "VERBOSE" for <tag1>
adb shell setprop log.tag.<tag1> VERBOSE

# Set the minimum log priority to "VERBOSE" for <tag1> persistently
adb shell setprop persist.log.tag.<tag1> VERBOSE

Trick 1: Filter with Tags and Priority

If I am interested in only some tags and priorities, then filter logs <tag>[:priority]. In practice, I usually do this.

# Suppress all logs and print all logs for <tag1> and <tag2>.
adb logcat -s <tag1> <tag2>

# Print all fatal logs + error logs for <tag1> + all logs for <tag2>
adb logcat *:F <tag1>:E <tag2>

You can also use highlighted color to match priority by adding -v color.

adb logcat -v color <other arguments>

Trick 2: Filter with Process

If I am interested in the log from a specific process, then print only the logs from that process with --pid.

# Print logs from the <package>:<process>.
adb logcat --pid=$(adb shell pidof -s <package>:<process>)

# Combining trick 1 and trick 2.
# Print the logs for <tag> from the <package>:<process>.
adb logcat --pid=$(adb shell pidof -s <package>:<process>) -s <tag>

Note that if the process crashes and restarts, the pid will change and we need to return the command with the new pid.

Trick 3: Filter with Regex

adb logcat itself can filter logs with regular expression without relying on grep.

adb logcat -e <regex>

This is similar to adb logcat | grep -E <regex> but should be more efficient since the filtered logs do not even get outputted. This is usually not a big deal but can save some bandwidth if the log is sent through the network (working remotely).

Trick 4: Read the Documentation

All my tricks above are well documented in adb logcat -h or the official doc. You might find even that can fit your need by reading it.