Timber — cos’è, API della libreria ed esempi di utilizzo

Autore: IT Sectr Pubblicato: 2026-05-28 Tempo di lettura: 8 min

Timber è una libreria di logging leggera per Android con architettura estensibile basata su alberi (Tree), che ha sostituito il standard android.util.Log in migliaia di progetti. Secondo GitHub, 2024, la libreria ha superato le 10.000 stelle ed è utilizzata in applicazioni con oltre 1 miliardo di installazioni. Timber risolve tre problemi principali dell’API Log: assenza di tag automatico, controllo obbligatorio isLoggable e natura statica delle chiamate.

Punti Chiave

  • Timber — un wrapper su android.util.Log con rilevamento automatico del tag tramite nome classe e stack di chiamate
  • Tree — l’elemento base dell’architettura Timber, ogni istanza definisce come elaborare un messaggio di log
  • Piantare alberi — il processo di registrazione di un Tree in Timber, solitamente eseguito una volta in Application.onCreate
  • DebugTree — un’implementazione incorporata per build Debug, invia i log a Logcat con il nome della classe come tag
  • Custom Tree — la possibilità di creare una propria implementazione per inviare log a Crashlytics, un file o un server

Cos’è Timber

Timber è una libreria open-source per Android creata da Jake Wharton nel 2013 come alternativa al android.util.Log standard. L’idea chiave di Timber è sostituire l’API Log statica con tag manuale obbligatorio con un meccanismo automatico che determina la fonte della chiamata tramite lo stack.

La libreria è costruita sul pattern architetturale Composite con Alberi (Tree). Invece di una singola classe Log con comportamento fisso, Timber gestisce una "foresta" di alberi — ogni albero è responsabile del proprio canale di output: console, file, Crashlytics, server remoto. Lo sviluppatore può aggiungere qualsiasi numero di alberi e combinarli.

Secondo Google I/O 2019, Timber è raccomandato da Google come best practice per il logging nelle applicazioni Android. La libreria occupa meno di 10 KB nell’APK e non ha dipendenze esterne, rendendola una scelta ideale per progetti di qualsiasi dimensione.

Timber risolve il problema dei tag incoerenti nei grandi team. Quando ogni sviluppatore scrive i tag manualmente, errori di battitura e discrepanze sono inevitabili — una classe viene registrata come "MainActivity", un’altra come "MAIN_ACTIVITY". Timber deriva automaticamente il tag dal nome della classe: MainActivity.kt → tag MainActivity.

Architettura di Timber: Alberi e Foresta

Architettura di Timber è composta da due componenti: la classe statica centrale Timber e la classe astratta Timber.Tree. Timber agisce come una facciata che delega ogni chiamata di log a tutti gli alberi piantati. Ogni albero decide se elaborare il messaggio e, in caso affermativo, dove inviarlo.

DebugTree — Implementazione incorporata per lo sviluppo

DebugTree è l’implementazione standard di Tree fornita con la libreria. Determina il tag analizzando lo stack di chiamate: sale di 8 frame dal punto di chiamata Timber.d() e trova il nome della classe che ha invocato il metodo di log. DebugTree si disattiva automaticamente (non produce output) nelle build release perché controlla BuildConfig.DEBUG.

Come funziona la Foresta

Forest (Foresta) — la collezione di tutti gli alberi piantati. Quando viene chiamato il metodo Timber.d("messaggio"), la libreria passa iterativamente il messaggio a tutti gli alberi nell’ordine in cui sono stati piantati. Ogni albero può filtrare il messaggio per livello, tag o contenuto e elaborarlo a modo suo.

L’ordine di piantagione è importante: il primo albero piantato viene elaborato per primo. Si raccomanda di piantare DebugTree per ultimo, in modo che gli alberi personalizzati (ad esempio, Crashlytics) elaborino il messaggio prima che raggiunga Logcat.

Sicurezza dei thread

Timber è thread-safe — tutti i metodi sono sincronizzati tramite un blocco interno. Questo garantisce che i messaggi provenienti da thread diversi non si mescolino. Tuttavia, all’interno di un albero personalizzato, la sincronizzazione è responsabilità dello sviluppatore: se l’albero scrive su un file, è necessario utilizzare synchronized o ReentrantLock.

kotlin
// Inizializzazione della foresta di alberi in Application.onCreate
class App : Application() {
    override fun onCreate() {
        super.onCreate()

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

        Timber.plant(CrashReportingTree())
        Timber.plant(FileLoggingTree())

        Timber.i("Timber planted with 3 trees")
    }
}

Installazione e configurazione di Timber in un progetto Android

Installazione di Timber si effettua aggiungendo una singola dipendenza a build.gradle. La libreria è pubblicata su Maven Central con l’artifact com.jakewharton.timber:timber. La versione attuale al 2024 è 5.0.1, l’ultimo aggiornamento stabile.

groovy
// build.gradle (Module: app)
dependencies {
    implementation 'com.jakewharton.timber:timber:5.0.1'
}

Configurazione minima dopo l’installazione — piantare DebugTree in Application.onCreate. Senza questo passaggio, Timber ignorerà tutte le chiamate di log senza lanciare eccezioni. Questo è un comportamento predefinito sicuro: se nessun albero viene piantato, la libreria funziona a vuoto con overhead minimo.

Secondo Jake Wharton, 2023, il 70% dei problemi di Timber per i nuovi utenti è legato a un’inizializzazione dimenticata o errata. Timber non genera un errore quando non ci sono alberi — gli sviluppatori si aspettano che i log appaiano in Logcat, ma non succede nulla.

Per i test, Timber fornisce Timber.asTree() — un metodo che restituisce l’albero corrente o null. Questo è comodo per i test unitari: è possibile sostituire l’albero con un mock e verificare che il messaggio di log sia stato inviato con il livello e il tag corretti.

Creazione di un Tree personalizzato per la gestione personalizzata dei log

Albero personalizzato — il motivo principale per utilizzare Timber invece dell’API Log standard. Sovrascrivendo i metodi di Tree, è possibile instradare i log di qualsiasi livello verso Crashlytics, il filesystem, Remote Config o il proprio server.

kotlin
class CrashReportingTree : Timber.Tree() {

    override fun isLoggable(tag: String?, priority: Int): Boolean {
        // Solo Error e WTF per crash-reporting
        return priority >= Log.ERROR
    }

    override fun log(priority: Int, tag: String?,
                   message: String, t: Throwable?) {
        if (t != null) {
            FirebaseCrashlytics.getInstance()
                .recordException(t)
        } else {
            FirebaseCrashlytics.getInstance()
                .log("[$tag] $message")
        }
    }
}

Metodi da sovrascrivere: isLoggable(tag, priority) — un filtro che determina se elaborare il messaggio (l’implementazione base restituisce true). log(priority, tag, message, t) — la logica di elaborazione principale. prepareLog(priority, tag, throwable, message, args) — chiamato prima della formattazione, permette di modificare il messaggio prima dell’elaborazione.

Un importante vantaggio degli alberi personalizzati è nessuna riflessione. A differenza di molti framework di logging, Timber non utilizza l’API Reflection per determinare il tag o il livello. Il tag viene calcolato analizzando lo stack di chiamate (Throwable.stackTrace), che è di ordini di grandezza più veloce.

Timber vs android.util.Log standard

Confronto tra Timber e l’API Log standard mostra quattro differenze chiave: tag automatico, supporto per la formattazione di stringhe con varargs, canali di output multipli e comportamento sicuro senza inizializzazione.

Parametroandroid.util.LogTimber
Rilevamento tagManuale, costante stringaAutomatico, tramite stack di chiamate
FormattazioneConcatenazione o String.formatVarargs integrati + segnaposto %s
Canali di outputSolo LogcatAlberi: Logcat, file, Crashlytics, ecc.
Comportamento senza inizializzazioneFunziona sempreNon produce output
PrestazioniLivello baseFormattazione pigra tramite isLoggable

Principale argomento contro Timber — dipendenza da una libreria di terze parti. Per un progetto semplice con logging minimo, l’uso di Timber può essere eccessivo. Tuttavia, secondo Google Play Console, 2024, oltre il 60% delle prime 1000 applicazioni su Google Play utilizzano Timber, confermandone l’affidabilità e l’efficienza.

Le prestazioni di Timber nelle build release sono paragonabili all’API Log standard. Quando non ci sono alberi piantati, il metodo Timber.d() verifica la presenza di alberi (un if) e ritorna — senza formattazione della stringa. Questo è più veloce di Log.d() con concatenazione, che viene sempre eseguita.

Best practice nell’uso di Timber

Prima regola — controlla sempre l’inizializzazione di Timber nei test. Usa Timber.asTree() per verificare che un albero sia piantato. Nei test unitari, pianta TestTree che salva i messaggi in una lista per controlli assert.

Seconda regola — non mescolare Timber e android.util.Log nello stesso progetto. Se il progetto usa già Timber, tutte le nuove chiamate di log devono passare attraverso di esso. La miscelazione porta a messaggi duplicati e confusione durante l’analisi.

Terza regola — pianta CrashReportingTree senza controllare BuildConfig.DEBUG. A differenza di DebugTree, l’albero di crash deve funzionare sia in debug che in release — questo garantisce che anche gli errori di test vengano catturati dal sistema di crash-reporting.

Quarta regola — usa i livelli integrati di Timber: Timber.v(), Timber.d(), Timber.i(), Timber.w(), Timber.e(), Timber.wtf(). Evita di chiamare Timber.log() direttamente con priorità numerica — questo riduce la leggibilità del codice e complica il refactoring.

Quinta regola — per librerie e moduli, usa Timber.tag("CustomTag"). Questo metodo restituisce un albero temporaneo con un tag sovrascritto senza influenzare la configurazione globale. Ciò consente di registrare dal codice della libreria con un identificatore personalizzato.

Domande Frequenti

Si può usare Timber in un modulo libreria Android?

— Timber è sicuro da usare nelle librerie. Se nessun albero viene piantato nell’applicazione, le chiamate Timber non causano errori. Per le librerie, si consiglia di utilizzare Timber.tag("LibraryTag") per identificare la fonte dei log.

Come determina Timber il tag senza specifica manuale?

Tramite lo stack di chiamate (stack trace) — DebugTree sale di 8 frame dal punto di chiamata Timber.d() ed estrae il nome della classe. Il metodo Throwable.stackTrace viene utilizzato per determinare la classe chiamante senza overhead dell’API Reflection.

In cosa Timber è diverso da Logcat?

Logcat è un’utilità di sistema Android per visualizzare i log. Timber è una libreria per scrivere log. Timber invia messaggi a Logcat tramite DebugTree, ma può anche inviarli a file, Crashlytics, Sentry e altri canali tramite alberi personalizzati.

Timber supporta Kotlin Multiplatform?

No — Timber è legato all’Android SDK (android.util.Log). Per progetti KMP, considera Kermit o Napier — librerie di logging multipiattaforma con architettura ad albero simile, funzionanti su Android, iOS, JVM e JS.

Come rimuovere tutti gli alberi piantati in Timber?

Usa Timber.uprootAll() — il metodo rimuove tutti gli alberi registrati. Timber.uproot(tree) rimuove un albero specifico. Questo è utile nei test per resettare lo stato tra i metodi di test.

Riepilogo

  • Timber — un wrapper leggero su android.util.Log con tag automatico e architettura ad albero
  • Tree — l’elemento base, ogni albero definisce il proprio canale di output dei log
  • DebugTree — implementazione incorporata per Logcat, automaticamente disattivata in release
  • Custom Tree — invia log a Crashlytics, file, server o qualsiasi altro canale
  • Timber.tag() — cambio temporaneo del tag per il codice di libreria senza configurazione globale
  • Sicurezza dei thread — tutti i metodi Timber sono sincronizzati, gli alberi personalizzati richiedono una propria sincronizzazione
  • Silenzio sicuro — quando non ci sono alberi, Timber non lancia eccezioni e non consuma risorse

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche