Timber — isang magaan na library ng pag-log para sa Android na may napapalawak na arkitektura batay sa mga puno (Tree), na pumalit sa karaniwang android.util.Log sa libu-libong proyekto. Ayon sa datos ng GitHub, 2024, ang library ay nakaipon ng mahigit 10,000 bituin at ginagamit sa mga app na may audience na mahigit 1 bilyong pag-install. Nilulutas ng Timber ang tatlong pangunahing problema ng Log API: kawalan ng awtomatikong tag, mandatoryong pagsusuri ng isLoggable at static na kalikasan ng mga tawag.
Mga Pangunahing Punto
Timber — ay isang open-source library para sa Android, na ginawa ni Jake Wharton noong 2013 bilang alternatibo sa karaniwang android.util.Log. Ang pangunahing ideya ng Timber — palitan ang static na Log API na may mandatoryong manual tag ng isang awtomatikong mekanismo na tumutukoy sa pinagmulan ng tawag sa pamamagitan ng stack.
Ang library ay binuo sa pattern ng arkitektura na Composite na may mga puno (Tree). Sa halip na isang solong Log class na may nakapirming pag-uugali, pinamamahalaan ng Timber ang isang “kagubatan” ng mga puno — bawat puno ay responsable para sa sarili nitong channel ng output: console, file, Crashlytics, malayuang server. Maaaring magdagdag ang developer ng anumang bilang ng mga puno at pagsamahin ang mga ito.
Ayon sa datos ng Google I/O 2019, inirerekomenda ng Google ang Timber bilang pinakamahusay na kasanayan para sa pag-log sa mga Android app. Ang library ay sumasakop ng mas mababa sa 10 KB sa APK at walang panlabas na dependencies, ginagawa itong perpektong pagpipilian para sa mga proyekto ng anumang laki.
Nilulutas ng Timber ang problema ng hindi pare-parehong mga tag sa malalaking koponan. Kapag ang bawat developer ay sumulat ng tag nang manu-mano, ang mga typo at pagkakaiba ay hindi maiiwasan — isang klase ay nagla-log bilang “MainActivity”, isa pa bilang “MAIN_ACTIVITY”. Awtomatikong kinukuha ng Timber ang tag mula sa pangalan ng klase:MainActivity.kt → tag MainActivity.
Ang arkitektura ng Timber ay binubuo ng dalawang bahagi: ang sentral na static na klase na Timber at ang abstract na klase na Timber.Tree. Ang Timber ay gumaganap bilang isang facade na nagtatalaga ng bawat log call sa lahat ng nakatanim na (planted) puno. Bawat puno ay nagpapasya kung kailangan nitong iproseso ang mensahe, at kung oo — saan ito ididirekta.
DebugTree — ang karaniwang implementasyon ng Tree na kasama ng library. Tinutukoy nito ang tag sa pamamagitan ng pagsusuri ng call stack: tumaas ng 8 frame mula sa punto ng tawag ng Timber.d() at hinahanap ang pangalan ng klase na tumawag sa log method. Awtomatikong nadi-disable ang DebugTree (walang inilalabas) sa release builds dahil sinusuri nito ang BuildConfig.DEBUG.
Forest (kagubatan) — ang koleksyon ng lahat ng nakatanim na puno. Kapag tinawag ang pamamaraang Timber.d(“mensahe”), ang library ay paulit-ulit na nagpapadala ng mensahe sa lahat ng puno sa pagkakasunud-sunod ng pagtatanim. Bawat puno ay maaaring mag-filter ng mensahe ayon sa antas, tag, o nilalaman at iproseso ito sa sarili nitong paraan.
Mahalaga ang pagkakasunud-sunod ng pagtatanim: ang unang nakatanim na puno ay unang pinoproseso. Inirerekomenda na itanim ang DebugTree bilang huli, upang ang mga kustom na puno (hal. Crashlytics) ay maproseso ang mensahe bago ito makarating sa Logcat.
Ang Timber ay ligtas para sa thread — lahat ng pamamaraan ay naka-synchronize sa pamamagitan ng internal lock. Ginagarantiyahan nito na ang mga mensahe mula sa iba't ibang thread ay hindi maghahalo. Gayunpaman, sa loob ng isang kustom na puno, ang synchronization ay nasa responsibilidad ng developer: kung ang puno ay sumusulat sa isang file, dapat gamitin ang synchronized o ReentrantLock.
// Pagsisimula ng kagubatan ng mga puno sa 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")
}
}
Pag-install ng Timber ay ginagawa sa pamamagitan ng pagdaragdag ng isang dependency sa build.gradle. Ang library ay nai-publish sa Maven Central sa ilalim ng artifact na com.jakewharton.timber:timber. Kasalukuyang bersyon para sa 2024 — 5.0.1, huling stable na update.
// build.gradle (Module: app)
dependencies {
implementation 'com.jakewharton.timber:timber:5.0.1'
}
Pinakamababang pagsasaayos pagkatapos ng pag-install — pagtatanim ng DebugTree sa Application.onCreate. Kung wala ang hakbang na ito, babalewalain ng Timber ang lahat ng log call, nang hindi nagtatapon ng exceptions. Ito ay isang ligtas na default na pag-uugali: kung ang puno ay hindi nakatanim, ang library ay tumatakbo nang walang ginagawa na may minimal na overhead.
Ayon sa datos ng Jake Wharton, 2023, 70% ng mga problema sa Timber sa mga bagong user ay may kaugnayan sa nakalimutan o maling pagsisimula. Hindi nagkakamali ang Timber kapag walang puno — inaasahan ng mga developer na lalabas ang log sa Logcat, ngunit walang nangyayari.
Para sa pagsubok, nagbibigay ang Timber ng Timber.asTree() — isang pamamaraan na nagbabalik ng kasalukuyang puno o null. Ito ay maginhawa para sa pagsusuri sa unit test: maaaring palitan ang puno ng mock at suriin kung ang log message ay naipadala na may tamang antas at tag.
Kustom na puno — ang pangunahing dahilan para gamitin ang Timber sa halip na karaniwang Log API. Sa pamamagitan ng pag-override ng mga pamamaraan ng Tree, maaaring idirekta ang log ng anumang antas sa Crashlytics, file system, Remote Config, o sariling server.
class CrashReportingTree : Timber.Tree() {
override fun isLoggable(tag: String?, priority: Int): Boolean {
// Error at WTF lang para sa 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")
}
}
}
Mga pamamaraang maaaring i-override: isLoggable(tag, priority) — filter na tumutukoy kung kailangan iproseso ang mensahe (ang base implementasyon ay nagbabalik ng true). log(priority, tag, message, t) — pangunahing lohika ng pagproseso. prepareLog(priority, tag, throwable, message, args) — tinatawag bago ang pag-format, pinapayagan baguhin ang mensahe bago ito iproseso.
Isang mahalagang bentahe ng kustom na mga puno — kawalan ng reflection. Hindi tulad ng maraming logging framework, hindi ginagamit ng Timber ang Reflection API para matukoy ang tag o antas. Ang tag ay kinakalkula sa pamamagitan ng pagsusuri ng call stack (Throwable.stackTrace), na gumagana nang mas mabilis.
Paghahambing ng Timber sa karaniwang Log API ay nagpapakita ng apat na pangunahing pagkakaiba: awtomatikong tag, suporta para sa pag-format ng string na may varargs, posibilidad ng maramihang output channel, at ligtas na pag-uugali kapag walang pagsisimula.
| Parameter | android.util.Log | Timber |
|---|---|---|
| Pagtukoy ng tag | Manual, string constant | Awtomatiko, batay sa call stack |
| Pag-format | Concatenation o String.format | Built-in na varargs + placeholder %s |
| Output channel | Logcat lang | Mga puno: Logcat, file, Crashlytics atbp. |
| Pag-uugali nang walang pagsisimula | Laging gumagana | Walang inilalabas |
| Pagganap | Batayang antas | Mabagal na pag-format sa pamamagitan ng isLoggable |
Pangunahing argumento laban sa Timber — dependency sa isang third-party na library. Para sa isang simpleng proyekto na may minimal na pag-log, ang paggamit ng Timber ay maaaring sobra. Gayunpaman, ayon sa datos ng Google Play Console, 2024, mahigit 60% ng top-1000 na app sa Google Play ang gumagamit ng Timber, na nagpapatunay ng pagiging maaasahan at kahusayan nito.
Ang pagganap ng Timber sa release builds ay hindi mababa sa karaniwang Log API. Kapag walang nakatanim na puno, ang pamamaraang Timber.d() ay sumusuri sa presensya ng mga puno (isang if) at bumabalik — nang walang pag-format ng string. Ito ay mas mabilis kaysa sa Log.d() na may concatenation na palaging isinasagawa.
Unang panuntunan — palaging suriin ang pagsisimula ng Timber sa mga test. Gamitin ang Timber.asTree() upang patunayan na ang puno ay nakatanim. Sa unit test, magtanim ng TestTree na nag-iimbak ng mga mensahe sa isang listahan para sa assert checks.
Ikalawang panuntunan — huwag paghaluin ang Timber at android.util.Log sa iisang proyekto. Kung ang proyekto ay gumagamit na ng Timber, lahat ng bagong log call ay dapat dumaan dito. Ang paghahalo ay humahantong sa pagdoble ng mga mensahe at kalituhan sa pagsusuri.
Ikatlong panuntunan — itanim ang CrashReportingTree nang walang pagsusuri ng BuildConfig.DEBUG. Hindi tulad ng DebugTree, ang crash tree ay dapat gumana pareho sa debug at release — ginagarantiyahan nito na ang mga error sa pagsubok ay mapupunta rin sa crash-reporting system.
Ikaapat na panuntunan — gamitin ang built-in na antas ng Timber: Timber.v(), Timber.d(), Timber.i(), Timber.w(), Timber.e(), Timber.wtf(). Iwasan ang direktang pagtawag sa Timber.log() na may numerikong priority — nababawasan nito ang pagiging madaling mabasa ng code at nagpapahirap sa refactoring.
Ikalimang panuntunan — para sa mga library at module, gamitin ang Timber.tag(“CustomTag”). Ang pamamaraang ito ay nagbabalik ng pansamantalang puno na may override na tag, nang hindi naaapektuhan ang global configuration. Pinapayagan nito ang pag-log mula sa library code na may kustom na identifier.
Mga Madalas Itanong
Oo — ang Timber ay ligtas gamitin sa mga library. Kung ang puno ay hindi nakatanim sa app, ang mga tawag sa Timber ay hindi nagdudulot ng mga error. Para sa mga library, inirerekomenda ang paggamit ng Timber.tag(“LibraryTag”) para sa pagtukoy ng pinagmulan ng log.
Sa pamamagitan ng call stack (stack trace) — ang DebugTree ay tumataas ng 8 frame mula sa punto ng tawag ng Timber.d() at kinukuha ang pangalan ng klase. Ang pamamaraang Throwable.stackTrace ay ginagamit upang matukoy ang tumatawag na klase nang walang gastos ng Reflection API.
Logcat — system utility ng Android para sa pagtingin ng mga log. Timber — library para sa pagsulat ng mga log. Ang Timber ay naglalabas ng mga mensahe sa Logcat sa pamamagitan ng DebugTree, ngunit maaari rin itong magpadala sa kanila sa mga file, Crashlytics, Sentry, at iba pang channel sa pamamagitan ng kustom na mga puno.
Hindi — ang Timber ay nakatali sa Android SDK (android.util.Log). Para sa KMP projects, isaalang-alang ang Kermit o Napier — mga multiplatform logging library na may katulad na arkitektura ng puno na gumagana sa Android, iOS, JVM, at JS.
Gamitin ang Timber.uprootAll() — ang pamamaraang ito ay nag-aalis ng lahat ng rehistradong puno. Timber.uproot(tree) ay nag-aalis ng isang partikular na puno. Ito ay kapaki-pakinabang sa mga test para i-reset ang estado sa pagitan ng mga pamamaraan ng pagsubok.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din