Library / SDK
JakeWharton/timber avatar
JakeWharton/timber

JakeWharton/timber: an Android logging wrapper with lint rules built in

A logger with a small, extensible API which provides utility on top of Android's normal Log class.

10,854 stars995 forksKotlinApache-2.0

At a glance

What is it?
Timber is a small Kotlin logging API that sits on top of Android's Log class, routing calls through installable Tree instances. It is for Android developers who want automatic class-name tags and compile-time checks on format strings, not for teams who need log shipping out of the box.
Who is it for?
Adopt Timber if you are writing an Android app and want class-name tags without passing a tag on every call, plus lint errors for mismatched format arguments. Skip it if you need a logging backend that uploads, rotates or persists logs without extra work, because no Tree ships enabled by default.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Kotlin, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The tag-passing problem Timber removes from Android logging

Android's Log class requires a tag on every call, so developers either repeat a constant string or pass a class name by hand. Timber takes the API surface of Log and adds one indirection: calls go to Tree instances, and the DebugTree implementation figures out from which class it is being called and uses that class name as its tag. The README states that because the tags vary, this pairs well with a log reader such as Pidcat. The audience is Android developers building apps, not backend services; the repository is Kotlin, and the sample app lives in timber-sample/. There is also a deliberate stance in the README: no Tree implementations are installed by default, with the stated reason that every time you log in production, a puppy dies. That is a design decision, not an oversight, and it shapes everything about how the library is adopted.

How Tree instances, planting and DebugTree tagging work together

Behaviour is added through Tree instances, and an instance is installed by calling Timber.plant. The README says installation should be done as early as possible, and names the onCreate of your application as the most logical choice. From then on, the static methods on Timber forward to every planted Tree, so one call site can feed a debug console tree and a crash-reporting tree at the same time. DebugTree derives the tag from the calling class rather than from a string you supply. The repository layout confirms the split: the timber/ module holds the library, timber-lint/ holds the lint rules, timber-sample/ holds a runnable example, and a CHANGELOG.md sits at the top level. What the README does not document is the ordering or threading contract between multiple planted trees, so if you plant more than one you are relying on the source rather than the prose.

Installing timber from Maven Central and planting your first Tree

The README gives the dependency coordinates directly. Add the repository and the artifact to your module's build file. The release named in the README is 5.0.1, and the Maven coordinates are com.jakewharton.timber:timber.

groovy
repositories {
  mavenCentral()
}

dependencies {
  implementation 'com.jakewharton.timber:timber:5.0.1'
}

Next, plant a tree. The README states that installation goes in the onCreate of your application class and that DebugTree is the implementation that derives the tag, so the call is Timber.plant with a DebugTree instance. No such snippet is printed in the README, so there is nothing further to copy here: write the plant call yourself, guarded by whatever debug flag your project already uses. After that, call the static methods anywhere in the app. The README's lint examples show the call style, including Timber.d with a format string and arguments, and Timber.tag(...).d(...) when you want to override the derived tag. A development build should print to Logcat with the enclosing class name as the tag. Snapshots of the development version are also published: the README points at the Sonatype snapshots repository and the 5.1.0-SNAPSHOT artifact, with documentation at the latest path rather than the 5.x path.

The embedded lint rules are the part that changes daily behaviour

Timber ships lint rules inside the library, and they are stricter than most logging wrappers bother to be. TimberArgCount and TimberArgTypes are errors: the first catches a format string that needs two arguments when the call supplies one, the second catches an argument whose type does not match the conversion, as in a %b conversion receiving a String. TimberTagLength is also an error, flagging tags longer than Android's maximum of 23 characters. The remaining three are warnings. LogNotTimber flags uses of Android's Log that should be Timber. StringFormatInTimber flags String.format inside a Timber call, and BinaryOperationInTimber flags string concatenation, both because Timber handles formatting itself. TimberExceptionLogging flags null or empty messages and the redundant pattern of passing an exception's own message when logging the exception. These checks run as part of your normal lint pass, which means the cost of the library is not only a runtime dependency but a set of build-time constraints on how your team writes log statements.

Where Timber is the wrong tool

The default configuration logs nothing. If you plant no trees, every Timber call is a no-op, and the README treats that as the correct default rather than something to work around. Teams expecting a logging framework that writes files, rotates them, batches uploads or attaches breadcrumbs to crash reports will not find that here; the README describes behaviour added through Tree instances and points at the sample app, and it does not document a bundled file or network tree. The lint rules are another boundary. They are errors, not warnings, for argument count, argument type and tag length, so a codebase migrating from Log with hand-built strings will fail the build until those call sites are rewritten. And the documentation is thin on the mechanics most teams eventually ask about: the README does not document rollback, tree removal, or what happens when a tree throws during logging.

Timber against a full logging facade such as SLF4J

The nearest conceptual alternative is a logging facade like SLF4J, which also separates call sites from backends. The approach differs in what the abstraction is built around. SLF4J binds one backend per classpath through a service loader and leaves tagging to the backend's configuration, while Timber keeps Android's Log signature, including the tag concept, and lets you plant several Tree instances at runtime from application code. That runtime planting is what makes Timber convenient for the common Android pattern of a verbose tree in debug builds and a reporting tree in release builds, switched by a single conditional. It is also why Timber is not portable: the API is shaped around Android, the lint rules are Android lint rules, and the tag-length check encodes a platform limit. If you are writing shared Kotlin code that also runs on the JVM, a facade with a platform-neutral API will serve you better than Timber.

Maintenance, releases and the Apache-2.0 licence

The repository is not archived, and the last push was on 2026-09-18, so the codebase is still receiving commits. Release cadence is a separate matter: the recent releases listed are 5.0.0 on 2021-08-10 and 5.0.1 on 2021-08-13, and the README still names 5.0.1 as the dependency to use. Anyone planning an upgrade should read CHANGELOG.md at the repository root rather than assume the snapshot line is stable; the README directs snapshot users to 5.1.0-SNAPSHOT and to the latest documentation path. Timber is licensed under Apache-2.0, and the README carries the standard notice that the software is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. Apache-2.0 permits commercial and closed-source use and requires that the licence and notices be preserved, but the exact obligations depend on how you redistribute, so read LICENSE.txt and your own legal guidance rather than treating this paragraph as advice.

Editorial conclusion

Adopt Timber if you are writing an Android app and want class-name tags without passing a tag on every call, plus lint errors for mismatched format arguments. Skip it if you need a logging backend that uploads, rotates or persists logs without extra work, because no Tree ships enabled by default. Before committing, verify the 5.0.1 artifact resolves from Maven Central in your build and decide which Tree implementations you will plant in Application.onCreate.

Frequently asked questions

Does Timber log anything if I do not plant a Tree?

No. The README states there are no Tree implementations installed by default, so calls do nothing until you call Timber.plant. Installation should happen as early as possible, typically in the onCreate of your application class.

How does DebugTree choose the tag for a log line?

According to the README, DebugTree automatically figures out from which class it is being called and uses that class name as its tag. Because tags vary per call site, the README notes it works well with a log reader like Pidcat.

What lint rules does Timber add to my Android build?

The README lists TimberArgCount, TimberArgTypes and TimberTagLength as errors, plus LogNotTimber, StringFormatInTimber, BinaryOperationInTimber and TimberExceptionLogging as warnings. The first three fail the build on wrong argument counts, wrong argument types or tags longer than 23 characters.

Which version of com.jakewharton.timber:timber should I depend on?

The README's download section shows com.jakewharton.timber:timber:5.0.1 from Maven Central, and the recent releases list 5.0.1 from 2021-08-13. A 5.1.0-SNAPSHOT is available from Sonatype's snapshots repository if you want the development version.

Official sources

  1. JakeWharton/timber on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/jakewharton-timber.svg)](https://hysenlabs.com/projects/jakewharton-timber)