Timber — lehká knihovna pro logování pro Android s rozšiřitelnou architekturou založenou na stromech (Tree), která nahradila standardní android.util.Log v tisících projektů. Podle údajů GitHub, 2024 knihovna nasbírala více než 10 000 hvězdiček a používá se v aplikacích s publikem přes 1 miliardu instalací. Timber řeší tři hlavní problémy Log API: chybějící automatický tag, povinnou kontrolu isLoggable a statickou povahu volání.
Hlavní body
Timber — je open-source knihovna pro Android, vytvořená Jakem Whartonem v roce 2013 jako alternativa ke standardnímu android.util.Log. Klíčovou myšlenkou Timber je nahradit statické Log API s povinným ručním tagem automatickým mechanismem, který určuje zdroj volání pomocí zásobníku.
Knihovna je postavena na architektonickém vzoru Composite se stromy (Tree). Místo jediné třídy Log s pevným chováním spravuje Timber „les“ stromů — každý strom je odpovědný za svůj výstupní kanál: konzoli, soubor, Crashlytics, vzdálený server. Vývojář může přidat libovolný počet stromů a kombinovat je.
Podle údajů Google I/O 2019 je Timber doporučován Googlem jako nejlepší praxe pro logování v Android aplikacích. Knihovna zabírá méně než 10 KB v APK a nemá žádné externí závislosti, což ji činí ideální volbou pro projekty jakékoli velikosti.
Timber řeší problém nekonzistentních tagů ve velkých týmech. Když každý vývojář píše tag ručně, jsou překlepy a rozdíly nevyhnutelné — jedna třída se loguje jako „MainActivity“, druhá jako „MAIN_ACTIVITY“. Timber automaticky extrahuje tag z názvu třídy:MainActivity.kt → tag MainActivity.
Architektura Timber se skládá ze dvou komponent: centrální statické třídy Timber a abstraktní třídy Timber.Tree. Timber funguje jako fasáda, která deleguje každé logovací volání na všechny zasazené (planted) stromy. Každý strom rozhoduje, zda má zprávu zpracovat, a pokud ano — kam ji nasměrovat.
DebugTree — standardní implementace Tree dodávaná s knihovnou. Určuje tag analýzou zásobníku volání: zvedne se o 8 rámců nad bod volání Timber.d() a najde název třídy, která zavolala logovací metodu. DebugTree se automaticky vypne (nic nevypisuje) v release sestaveních, protože kontroluje BuildConfig.DEBUG.
Forest (les) — kolekce všech zasazených stromů. Když je zavolána metoda Timber.d(„zpráva”), knihovna iterativně předává zprávu všem stromům v pořadí zasazení. Každý strom může zprávu filtrovat podle úrovně, tagu nebo obsahu a zpracovat ji svým způsobem.
Pořadí zasazení je důležité: první zasazený strom se zpracovává jako první. Doporučuje se zasadit DebugTree jako poslední, aby vlastní stromy (např. Crashlytics) zpracovaly zprávu dříve, než se dostane do Logcatu.
Timber je bezpečný pro vlákna — všechny metody jsou synchronizovány prostřednictvím interního zámku. To zaručuje, že se zprávy z různých vláken nepromíchají. Uvnitř vlastního stromu však synchronizace leží na vývojáři: pokud strom zapisuje do souboru, je nutné použít synchronized nebo ReentrantLock.
// Inicializace lesa stromů v 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")
}
}
Instalace Timber se provádí přidáním jedné závislosti do build.gradle. Knihovna je publikována v Maven Central pod artefaktem com.jakewharton.timber:timber. Aktuální verze pro rok 2024 — 5.0.1, poslední stabilní aktualizace.
// build.gradle (Module: app)
dependencies {
implementation 'com.jakewharton.timber:timber:5.0.1'
}
Minimální nastavení po instalaci — zasazení DebugTree do Application.onCreate. Bez tohoto kroku bude Timber ignorovat všechna logovací volání, aniž by házel výjimky. Toto je bezpečné výchozí chování: pokud strom není zasazen, knihovna pracuje naprázdno s minimální režií.
Podle údajů Jake Wharton, 2023 souvisí 70% problémů s Timber u nových uživatelů se zapomenutou nebo nesprávnou inicializací. Timber negeneruje chybu při absenci stromů — vývojáři očekávají, že se logy objeví v Logcatu, ale nic se neděje.
Pro testování poskytuje Timber Timber.asTree() — metodu, která vrací aktuální strom nebo null. To je vhodné pro kontrolu v unit testech: strom lze nahradit mockem a zkontrolovat, zda byla log zpráva odeslána se správnou úrovní a tagem.
Vlastní strom — hlavní důvod pro použití Timber místo standardního Log API. Přepsáním metod Tree lze nasměrovat logy libovolné úrovně do Crashlytics, souborového systému, Remote Config nebo vlastního serveru.
class CrashReportingTree : Timber.Tree() {
override fun isLoggable(tag: String?, priority: Int): Boolean {
// Pouze Error a WTF pro 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")
}
}
}
Metody k přepsání: isLoggable(tag, priority) — filtr určující, zda zpracovat zprávu (základní implementace vrací true). log(priority, tag, message, t) — hlavní logika zpracování. prepareLog(priority, tag, throwable, message, args) — volá se před formátováním, umožňuje změnit zprávu před zpracováním.
Důležitá výhoda vlastních stromů — absence reflexe. Na rozdíl od mnoha logovacích frameworků Timber nepoužívá Reflection API k určení tagu nebo úrovně. Tag se vypočítává analýzou zásobníku volání (Throwable.stackTrace), což pracuje řádově rychleji.
Srovnání Timber se standardním Log API ukazuje čtyři klíčové rozdíly: automatický tag, podpora formátování řetězců s varargs, možnost více výstupních kanálů a bezpečné chování při absenci inicializace.
| Parametr | android.util.Log | Timber |
|---|---|---|
| Určení tagu | Ruční, řetězcová konstanta | Automatické, podle zásobníku volání |
| Formátování | Konkatenace nebo String.format | Vestavěný varargs + zástupný znak %s |
| Výstupní kanály | Pouze Logcat | Stromy: Logcat, soubor, Crashlytics atd. |
| Chování bez inicializace | Vždy funguje | Nic nevypisuje |
| Výkon | Základní úroveň | Líné formátování přes isLoggable |
Hlavní argument proti Timber — závislost na knihovně třetí strany. Pro jednoduchý projekt s minimálním logováním může být použití Timber nadbytečné. Nicméně podle údajů Google Play Console, 2024 používá více než 60% top-1000 aplikací v Google Play Timber, což potvrzuje jeho spolehlivost a efektivitu.
Výkon Timber v release sestaveních není horší než standardní Log API. Při absenci zasazených stromů metoda Timber.d() zkontroluje přítomnost stromů (jeden if) a vrátí se — bez formátování řetězce. To je rychlejší než Log.d() s konkatenací, která se provádí vždy.
První pravidlo — vždy kontrolujte inicializaci Timber v testech. Použijte Timber.asTree() pro ověření, že je strom zasazen. V unit testech zasaďte TestTree, který ukládá zprávy do seznamu pro assert kontroly.
Druhé pravidlo — nemíchejte Timber a android.util.Log v jednom projektu. Pokud projekt již používá Timber, všechna nová logovací volání by měla procházet přes něj. Míchání vede k duplikování zpráv a zmatku při analýze.
Třetí pravidlo — zasaďte CrashReportingTree bez kontroly BuildConfig.DEBUG. Na rozdíl od DebugTree by měl crash strom fungovat jak v debug, tak v release režimu — to zaručuje, že testovací chyby se také dostanou do crash-reporting systému.
Čtvrté pravidlo — používejte vestavěné úrovně Timber: Timber.v(), Timber.d(), Timber.i(), Timber.w(), Timber.e(), Timber.wtf(). Vyhněte se přímému volání Timber.log() s číselným priority — to snižuje čitelnost kódu a komplikuje refactoring.
Páté pravidlo — pro knihovny a moduly používejte Timber.tag(„CustomTag“). Tato metoda vrací dočasný strom s přepsaným tagem, aniž by ovlivnila globální konfiguraci. Umožňuje logování z knihovního kódu s vlastním identifikátorem.
Často kladené otázky
Ano — Timber je bezpečné používat v knihovnách. Pokud strom není zasazen v aplikaci, volání Timber nezpůsobují chyby. Pro knihovny se doporučuje používat Timber.tag(„LibraryTag“) pro identifikaci zdroje logů.
Přes zásobník volání (stack trace) — DebugTree se zvedne o 8 rámců nad bod volání Timber.d() a extrahuje název třídy. Metoda Throwable.stackTrace se používá k určení volající třídy bez nákladů Reflection API.
Logcat — systémový nástroj Androidu pro prohlížení logů. Timber — knihovna pro psaní logů. Timber vypisuje zprávy do Logcatu přes DebugTree, ale může je také odesílat do souborů, Crashlytics, Sentry a dalších kanálů prostřednictvím vlastních stromů.
Ne — Timber je vázán na Android SDK (android.util.Log). Pro KMP projekty zvažte Kermit nebo Napier — multiplatformní logovací knihovny s podobnou architekturou stromů, které fungují na Android, iOS, JVM a JS.
Použijte Timber.uprootAll() — tato metoda odstraní všechny registrované stromy. Timber.uproot(tree) odstraní konkrétní strom. To je užitečné v testech pro resetování stavu mezi testovacími metodami.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také