Sunday, 2 October 2011

Android: Implementing logging in your app

How much logging does one need?
How frequently should I log?
(How to use java.util.logging?)

Programming logging in your Android application
Eternal questions about logging and often they don't have a simple answer. Logs are important, even vital sometimes. I don't write anything that does not have some level of logging.
And when we're talking about logging for mobile apps, things can get more complicated.
Why? Well, logs are resources and resources in a mobile device are scarce (that's how I like to think anyway).

By telling the app to log something we are consuming CPU and generating I/O. So if we are iterating a large list something and logging every single iteration, we're probably using a lot of resources.

Which, again could be fine if the user is not being affected by that (if anything we're consuming power). It's all about how the user perceives the app whilst running.
So how to safely implement logging in your Android app?
Here's a few suggestions:

1) Use only 1 log file (do not rollover)
2) Limit it to a size you think is sufficient to capture enough information throughout the app's life cycle
3) collect error logs (by let's say, sending it to your app's remote server) but ONLY with user's agreement
4) log only what you need but with as much information as you can. You'll have to find the right balance for your app.
5) use the logging facilities existing in the SDK.

OK, less talk more code.
First let's learn how to create a logging mechanism using the java.util.logging package (that's right, not Android specific).

The java logging is very flexibly but basically we need 3 things
- a Logger object;
- a log handler;
- a log formatter;

the most simple combination of this 3 is used in the code snippet below

Logger myAppLog=Logger.getLogger("myAppLog"); FileHandler logHandler=new FileHandler("path_to_log.file",false); SimpleFormatter formatter=new SimpleFormatter(); logHandler.setFormatter(formatter); myAppLog.addHandler(logHandler);

The code uses a file as the output for the log messages and a simple text formatter.  By default the log file is in XML. You can write your own formatters just by extending one of the formatting classes.

We are done with the basic stuff, just call myAppLog.log(...), myAppLog.severe(...) or myAppLog.warning(...) however you think necessary. More information about these methods can be found here.

There are however a few details we must observe. All in this line of code

FileHandler logHandler=new FileHandler("path_to_log.file",false);

First the path to the log file. I recommend using the internal memory. I know, less space but has a faster access time. You can use methods like Context.getDir() to properly set a location for your log file.

The second parameter (boolean true) tells the log handler that we don't want to append, i.e, a new file is created every time.

Another thing is the size and number of log files. Remember that I suggested not rolling logs over and limiting the size? Well, we can't do that with the construction above.
For that we need to change that line to

FileHandler logHandler=new FileHandler("path_to_log.file", 100*1024, 1, false);

here we're telling the handler to limit the file to 100kb (100*1024) and to keep only 1 log file, always creating a new one.

Simple isn't it?
Let people know if you like this ;)

Programming tricks and tips for android developers