Android Toolkit: Timber for logging

Sometimes, is those little libraries that make a developer's work more pleasureful every day. Timber is one of those libraries, it makes Android logging simpler.



No more making up and carrying around tags any more. Timber sets the Log tag for you, with the class you're in.

Timber allows to easily print stack traces with no use of Tags.

Timber.e(exception)

While Timber does not require you to Tag each message and automatically use the current class, you can use custom tags if you wish to do so.

Timber.tag("Some Different tag").e("And error message")




Timber's log methods also have take a string, but they accept string format parameters after.

If your project still mainly uses java you can make use of formatted arguments.

Timber.d("Hello %s %s!", firstName)

And not just that, in the example above you would see a TimberArgCount error, yes Timber comes with Lint rules that help you see and solve issues quickly.




Logs are only printed on debug mode

You no longer have to worry about sending Logs to production. This because Timber can run in Debug Mode, you don't need to have to make a wrapper and copy-paste it in every project, simply:

public class ExampleApp extends Application {
  @Override public void onCreate() {
    super.onCreate();

    if (BuildConfig.DEBUG) {
      Timber.plant(new DebugTree());
    }
  }
}

And it's done.




Timber is easily extendible and configurable Timber is easily extensible, you can develop your own "Tree" and have custom behaviour on every log. Let's take the example given to us in the official Repository.

public class ExampleApp extends Application {
  @Override public void onCreate() {
    super.onCreate();

    if (BuildConfig.DEBUG) {
      Timber.plant(new DebugTree());
    } else {
      Timber.plant(new CrashReportingTree());
    }
  }

  /** A tree which logs important information for crash reporting. */
  private static class CrashReportingTree extends Timber.Tree {
    @Override protected void log(int priority, String tag, @NonNull String message, Throwable t) {
      if (priority == Log.VERBOSE || priority == Log.DEBUG) {
        return;
      }

      FakeCrashLibrary.log(priority, tag, message);

      if (t != null) {
        if (priority == Log.ERROR) {
          FakeCrashLibrary.logError(t);
        } else if (priority == Log.WARN) {
          FakeCrashLibrary.logWarning(t);
        }
      }
    }
  }
}

As you can see it's easy to create behaviour in every Log call with a single method call, if you want to upload custom logs and/or exceptions you can easily do it here.




Conclusion:

Loggers are a must have in every app as they help improve code quality and hunting bugs. When a project starts to grow using the Android Logger, normally ends up being inside a wrapper class that we can easily turn on and off and apply improvements, and as we switch projects we tend to copy and past it. So if we already tend to do this why not use Timber and make use of Lint rules, auto tags and many other powerful features already there for us?

This was the logic behind the creation of Timber and we strongly recommend other developers to use it. We had such a great experience in the last years with this small, but powerful library that it comes pre-configured in our Android Template.