Wednesday, October 17, 2012

Android protip: remove debug logs from release builds with Proguard

I use the android.util.Log extensively - often it's faster than starting the debugger and (unlike debugging) it's always on, which is invaluable when you're trying to track the root cause of some hard to reproduce bugs. Logging is also nice for release candidate builds you give to the QA team - if they find some bugs you'll have more information than just a stack trace.

On the other hand you don't want to keep all those logs for release builds, mostly for performance and privacy reasons. If you google around  for a solution to this issue you'll probably find a dozen ideas like using a wrapper for logging class, using a dedicated logging framework or even some sed/awk scripts to ant build process. Among those ideas is the one I'd like to recommend: customizing Proguard configuration.

Proguard is automatically run in release builds by ant and Export wizards from Eclipse and there is an optimization option, which can be used to disable logs:

-assumenosideeffects
Specifies methods that don't have any side effects (other than maybe returning a value). In the optimization step, ProGuard will then remove calls to such methods, if it can determine that the return values aren't used.
I wouldn't use this tool for the purpose stated in the manual, because even if my code doesn't have any side effects, the methods called from it might have ones; I'd rather use some static code analysis tool to find the unnecessary calls and manually remove them. It looks perfect for suppressing the logs though and it's very simple to set up - just add the following lines to the proguard-project.txt file generated by android command line tool:

-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** i(...);
    public static *** w(...);
    public static *** e(...);
}

You can of course keep some of the priority levels by removing lines from this config.

The nice thing about this solution is that you have to set it only once and it will just work for all further release builds.

UPDATE (August 2013): do not assume that Proguard will remove any code other than the methods listed in assumenosideeffects setting. See "Proguard gotcha" post for more details.

1 comment:

  1. Great idea. I always used to use:

    if(DEBUG_FLAG) Log.d(...);

    ReplyDelete