Improve logging and reporting with androlog

Professional development requires advanced logging configuration to avoid logcat from becoming bloated with irrelevant log information. Moreover, the current Android reporting support is not really useful as it lacks real data to reproduce and investigate the issue. akquinet Androlog is a library replacing the logging and reporting support of Android. It's customizable, easy to use and flexible.

  • Source Code: GitHub
  • License: Apache License 2.0

Motivations

When you're developing Android applications, you generally use the Android logger. However, this logging system is too simplistic to meet sophisticated application development requirement:

  • All log messages are displaying in the console (logcat), regardless the log level and the tag
  • There is no way to disable the logging easily without removing all Log.x calls. However this is required before uploading your application in the marketplace.
  • Android reporting was introduced in Android 2+, and is quite limited. Reports just contains the stack trace and a user message. Androlog reporting works on 1.6, contains the logged messages and stack traces. So Androlog reports allow a better understanding of the issues.

Brief description

Androlog is a pretty small library that you can embed in your Android application. Instead of calling android.util.Log, you just use de.akquinet.android.androlog.Log (a simple replace on the import statements works). The provided API is similar to the Android Log. So androlog provides the same log levels : VERBOSE, DEBUG, INFO, WARN, and ERROR with the same methods : Log.v, Log.d, Log.i, Log.w, Log.e.

The following code snippet use Androlog:

import de.akquinet.android.androlog.Log;

public class AndrologExample {
    public static final String TAG = "MY_TAG";
    public void doSomething() {
        Log.i(TAG, "A message");
    }
}

As you can see it is really similar to the Android log. However, this logging system can be configured to:

  • disabled all messages (for releases)
  • configure the log level per TAG,
  • configure a default log level
  • configure different logging policy per application

This page explains how to use Androlog.

Create an Android application project

First, you need an Android project. You can use Eclipse, Ant or Maven to achieve this task. In this tutorial, we just use Eclipse. So, make sure you have the Android Eclipse plugin installed as well as the Android SDK.

In Eclipse, Go to File - New - Project... - Android / Android Project.

Fill the new project wizard.

You can create a test project too, but it is not required.

Add Androlog to the project

Create a lib folder in your project, and copy the androlog jar in this folder. Right-click on the jar, and add it to the build path.

For Ant, you just need to add androlog to the project classpath. For maven, just add androlog as a dependency (in the compile scope).

Using Androlog

Open the MyActivity.java file, and add the Androlog initialization and a log message:

package my.application;

import de.akquinet.android.androlog.Log;
import android.app.Activity;
import android.os.Bundle;

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Initializes androlog
        // This will read the /sdcard/my.application.properties file
        Log.init(this);

        // Log a messgage
        Log.i(this, "This is a logged message");

        setContentView(R.layout.main);
    }
}

Run the application

Now it's time to run the application. Right clic on the project - Run As - Run as Android application. This will start an emulator, and start the application

Open logcat, either in the console (adb logcat) or in Eclipse. You will not see the logged message! Indeed, the log is disabled by default, this allows to simply remove all logged messages on regular/user phones. But don't worry, configuring logging is really simple.

Androlog configuration

Create a file named my.application.properties. The name is the application's package name + .properties. Edit the file to obtain: androlog.active=true. Push the file on the root of the sdcard:

adb push my.application.properties /sdcard/

Then restart the application. Look at logcat. You will see the logged message:

I/ActivityManager(   51): Starting activity: 
Intent { act=android.intent.action.MAIN 
cat=[android.intent.category.LAUNCHER] flg=0x10200000 
cmp=my.application/.MyActivity }
I/my.application.MyActivity(  215): This is a logged message
I/ActivityManager(   51): 
Displayed activity my.application/.MyActivity: 174 ms (total 174 ms)

That's it! You now have a way to enable / disable the logging in a pretty simple way without modifying your application code. Androlog provides a lot of configuration option, so don't forget to look to the documentation.

Why do I have to configure ?

By default, on a normal phone, Androlog does not log anything. This is perfect for released application which does not pollute the logcat output. Moreover, this is a requirement in the Android release process.

Androlog configuration can be done in two way:

  • with external files (recommended)
  • with the API

Configuring Androlog with external files

Androlog configuration files are just Java properties file (see java.util.Properties). Configurations are placed in the root of the SDCard of the phone or in the assets of the application. This later case is used for production configuration (especially for the reporting configuration). The configuration contained in the assets is ignore if a configuration is present on the SDCard.

The file name are either androlog.properties, a custom name, your application package name according to the init method that you use.

Initializing logging

In all the entry point of your application, you must call Log.init. This will initialize the logging and configure it. There are three init methods:

  • init() : read the /sdcard/androlog.properties file
  • init(name) : read the /sdcard/name.properties file
  • init(context) : read the /sdcard/application_package.properties file. The application package is the package declared in the AndroidManifest file.

Note: To support configuration from the assets, the init method arguments must contain the Android context.

If the read file does not exist, the logging is disabled, which means, on regular phone, it is disabled.

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.init(this); // Use the context method

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.intro);
        // ....
    }
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.init(); // Use the androlog.properties file

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.intro);
        // ....
    }
@Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.init("my-file"); // Use the my-file.properties file

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.intro);
        // ....
    }

All entry points must call the init method. Init methods can be called from Activities, Content Providers, Services ...

Configuring logging

Once initialized, the logging need to be configured. As said previously, the configuration files are simple java properties. A couple of 'special' keys allows global configuration:

  • androlog.active = true|false : enables or disabled the logging. This is a mandatory property which must be set to true to enable the logging. If set to false, nothing will be logged.
  • androlog.default.level=VERBOSE|DEBUG|INFO|WARN|ERROR : Sets the default log level. If not set, INFO is used.

Others keys (which does not start with androlog.) are tag names. It allows setting a specific log level for a specific tag. If package names are used for tags, it is possible to specify only a part of the package, i.e. a.b will match a.b.c and a.b.c.d in addtion to a.b:

  • my_tag_1 = VERBOSE
  • my.androlog = INFO // will match my.androlog or my.androlog.activity

The last configuration key is the configuration of the wtf delegation. On Android 2.2, those methods may cause the application to terminate. To avoid this behavior, you can set androlog.delegate.wtf to false.

Example of configurations

The minimum configuration to enable logging

androlog.active=true

The minimum configuration disabling logging

androlog.active=false

Set a default log level

androlog.active=true
androlog.default.level=WARN

Set a default log level and some specific levels

androlog.active=true
androlog.default.level=WARN
my.logger=INFO
de.akquinet.android.MyActivity=DEBUG

Troubleshooting

My logging are never displayed: Check that the init method are really called, and the associated file exist and contains androlog.active=true.

How do I disable the logging before releasing: You don't need, as the configuration file will probably not be present on a regular phone

Supported log levels and there associated methods

  • VERBOSE : Log.v
  • DEBUG : Log.d
  • INFO : Log.i
  • WARN : Log.w
  • ERROR : Log.e

Signatures

All the methods listed above supports different set of parameters:

  • (tag name, message) : the tag name is a string object identifying the logger.
  • (tag name, message, exception) : the tag name is a string object identifying the logger, exception is a Throwable object attached to the logged message.
  • (object, message) : the tag name is computed from the given object, so it use the qualified name of the given object. We generally use this.
  • (object, message, exception) : the tag name is computed from the given object, so it use the qualified name of the given object. We generally use this. Exception is a Throwable object attached to the logged message.
  • (message) : the tag name is computed from the current thread stack, so it uses the qualified name of the class logging the message as tag. This method is equivalent to (this, message).

Examples

package androlog.example;
import de.akquinet.android.androlog.Log;

public class AndrologExample {

    public void doSomething() {
		// Regular Android API
        Log.i("my tag", "a logged message");
		// the tag will be androlog.example.AndrologExample
        Log.i(this, "a logged message");
		// the tag will be androlog.example.AndrologExample
        Log.i("a logged message");     
	}
}

Note about (message) methods

The computation of the TAG from the current Thread stack is expensive as it requires an execution stack analysis.

Support of the 'What a Terrible Failure' methods.

Android 2.2 has introduced new log methods named wtf. Androlog provides methods delegating on those methods on Android 2.2. On prior versions, the message is logged using the ASSERT level. Those messages are always logged regardless the activation of the logger.

Note that the Android wtf methods may cause the application to terminate according to the system settings. To avoid this behavior, you can configure Androlog with androlog.delegate.wtf set to false.

Building Androlog

The build process is based on Maven and the maven-android-plugin (for the integration-tests).

Once downloaded, you should have:

pom.xml
androlog\
  src
  pom.xml
androlog-it\
  src
  res
  AndroidManifest.xml
  pom.xml

The first pom is the parent pom of the project. The androlog project contains Androlog it-self. It builds a jar file. Androlog-it contains integration-tests. Those tests are executed on an Android framework (emulator or real handset). To get further information about Android integration tests please read this page.

Prerequisites

Before building Android from the parent pom, you need to:

  • define the sdk.path property pointing on the Android SDK location. The recommended way it to edit the ~/.m2/settings.xml and to add:
    <profiles>
      <profile>
        <id>android</id>
       <properties>
         <!-- CHANGE HERE -->
         <sdk.path>/Users/clement/dev/android</sdk.path>
       </properties>
       </profile>
       <!-- others profiles -->
    </profiles>
    <activeProfiles>
        <activeProfile>android</activeProfile>
    </activeProfiles>
  • start an android emulator or plug your android development device. Tests will be executed on this emulator/device. Androlog supports Android 1.6+. The device must have a readable and writable SDCard. Use $ emulator -avd an_existing_avd to test this.

Building

Once everything configured, you can build androlog, from the root folder (parent pom directory), with $ mvn clean install.

Bug tracking

As androlog is hosted on github, we use the gihub issue tracking system. Just fill a ticket.

Download

You can download the Androlog sources from github. We also provides binaries for convenience:

  • androlog-1.0.6.jar (just add this jar to your build path)
  • Maven dependency (to use with the maven-android-plugin). Androlog is available on maven central, so you don't need to customize your maven settings.
    <dependency>
      <groupId>de.akquinet.android.androlog</groupId>
      <artifactId>androlog</artifactId>
      <version>1.0.1</version>
      <scope>compile</scope>
    </dependency>