Timber, genişletilebilir ağaç (Tree) tabanlı mimariye sahip, Android için hafif bir loglama kütüphanesidir ve binlerce projede standart android.util.Log'un yerini almıştır. GitHub, 2024 verilerine göre, kütüphane 10.000'den fazla yıldız toplamış ve 1 milyardan fazla yüklemesi olan uygulamalarda kullanılmaktadır. Timber, Log API'nin üç ana sorununu çözer: otomatik tag eksikliği, zorunlu isLoggable kontrolü ve çağrıların statik doğası.
Önemli Noktalar
Timber, Jake Wharton tarafından 2013 yılında standart android.util.Log'a alternatif olarak oluşturulmuş, Android için açık kaynaklı bir kütüphanedir. Timber'ın temel fikri, zorunlu manuel tag ile statik Log API'sini, yığın aracılığıyla çağrı kaynağını otomatik olarak belirleyen bir mekanizmayla değiştirmektir.
Kütüphane Ağaçlarla Bileşik (Composite with Trees) mimari deseni üzerine inşa edilmiştir. Sabit davranışa sahip tek bir Log sınıfı yerine, Timber bir ağaç "ormanı" yönetir — her ağaç kendi çıktı kanalından sorumludur: konsol, dosya, Crashlytics, uzak sunucu. Geliştirici istediği sayıda ağaç ekleyebilir ve bunları birleştirebilir.
Google I/O 2019'a göre Timber, Google tarafından Android uygulamalarında loglama için en iyi uygulama olarak önerilmektedir. Kütüphane APK'da 10 KB'dan az yer kaplar ve harici bağımlılığı yoktur, bu da onu her ölçekteki proje için ideal bir seçim haline getirir.
Timber, büyük ekiplerde tutarsız tag sorununu çözer. Her geliştirici tag'leri manuel olarak yazdığında, yazım hataları ve tutarsızlıklar kaçınılmazdır — bir sınıf "MainActivity" olarak, diğeri "MAIN_ACTIVITY" olarak kaydedilir. Timber, sınıf adından otomatik olarak tag çıkarır: MainActivity.kt → tag MainActivity.
Mimari iki bileşenden oluşur: merkezi statik sınıf Timber ve soyut sınıf Timber.Tree. Timber, her log çağrısını dikilmiş tüm ağaçlara devreden bir cephe (facade) görevi görür. Her ağaç, mesajı işleyip işlemeyeceğine ve işleyecekse nereye göndereceğine karar verir.
DebugTree, kütüphaneyle birlikte gelen standart Tree uygulamasıdır. Tag'i çağrı yığınını analiz ederek belirler: Timber.d() çağrı noktasından 8 kare yukarı çıkar ve log metodunu çağıran sınıfın adını bulur. DebugTree, BuildConfig.DEBUG değişkenini kontrol ettiği için release yapılarında otomatik olarak devre dışı kalır (hiçbir şey çıktılamaz).
Forest (Orman) — dikilmiş tüm ağaçların koleksiyonudur. Timber.d("mesaj") metodu çağrıldığında, kütüphane mesajı dikilme sırasına göre tüm ağaçlara yinelenerek iletir. Her ağaç mesajı seviye, tag veya içeriğe göre filtreleyebilir ve kendi yöntemiyle işleyebilir.
Dikme sırası önemlidir: ilk dikilen ağaç ilk işlenir. Özel ağaçların (örneğin Crashlytics) mesajı Logcat'e ulaşmadan önce işlemesi için DebugTree'nin en son dikilmesi önerilir.
Timber iş parçacığı güvenlidir — tüm metotlar dahili bir kilit aracılığıyla senkronize edilir. Bu, farklı iş parçacıklarından gelen mesajların karışmamasını garanti eder. Ancak, özel bir ağacın içinde senkronizasyon geliştiricinin sorumluluğundadır: ağaç bir dosyaya yazıyorsa, synchronized veya ReentrantLock kullanılmalıdır.
// Application.onCreate'te ağaç ormanının başlatılması
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")
}
}
Kurulum, build.gradle'a tek bir bağımlılık eklenerek yapılır. Kütüphane Maven Central'da com.jakewharton.timber:timber yapıtı altında yayınlanmıştır. 2024 itibarıyla güncel sürüm 5.0.1, son kararlı güncellemedir.
// build.gradle (Module: app)
dependencies {
implementation 'com.jakewharton.timber:timber:5.0.1'
}
Kurulumdan sonra minimum yapılandırma — Application.onCreate'te DebugTree dikmek. Bu adım olmadan, Timber hiçbir istisna fırlatmadan tüm log çağrılarını yok sayar. Bu güvenli bir varsayılan davranıştır: hiçbir ağaç dikilmezse, kütüphane minimum ek yük ile boşta çalışır.
Jake Wharton, 2023'e göre, yeni kullanıcıların Timber sorunlarının %70'i unutulan veya yanlış başlatmayla ilgilidir. Ağaç olmadığında Timber hata üretmez — geliştiriciler Logcat'te logların görünmesini bekler, ancak hiçbir şey olmaz.
Test için Timber, Timber.asTree() sağlar — geçerli ağacı veya null döndüren bir metot. Bu, birim testler için kullanışlıdır: ağacı bir mock ile değiştirebilir ve log mesajının doğru seviye ve tag ile gönderildiğini doğrulayabilirsiniz.
Özel ağaç — standart Log API yerine Timber kullanmanın ana nedenidir. Tree metotlarını geçersiz kılarak, herhangi bir seviyedeki logları Crashlytics, dosya sistemi, Remote Config veya kendi sunucunuza yönlendirebilirsiniz.
class CrashReportingTree : Timber.Tree() {
override fun isLoggable(tag: String?, priority: Int): Boolean {
// Crash raporlama için yalnızca Error ve WTF
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")
}
}
}
Geçersiz kılınabilecek metotlar: isLoggable(tag, priority) — mesajın işlenip işlenmeyeceğini belirleyen bir filtre (temel uygulama true döndürür). log(priority, tag, message, t) — ana işleme mantığı. prepareLog(priority, tag, throwable, message, args) — biçimlendirmeden önce çağrılır, mesajın işlenmeden önce değiştirilmesine izin verir.
Özel ağaçların önemli bir avantajı yansıma (reflection) olmamasıdır. Birçok loglama çerçevesinin aksine Timber, tag veya seviyeyi belirlemek için Reflection API kullanmaz. Tag, çağrı yığını (Throwable.stackTrace) analiz edilerek hesaplanır ve bu, katbekat daha hızlı çalışır.
Karşılaştırma Timber ve standart Log API arasında dört temel fark gösterir: otomatik tag, varargs ile dize biçimlendirme desteği, birden çok çıktı kanalı ve başlatma olmadan güvenli davranış.
| Parametre | android.util.Log | Timber |
|---|---|---|
| Tag algılama | Manuel, dize sabiti | Otomatik, çağrı yığını aracılığıyla |
| Biçimlendirme | Birleştirme veya String.format | Yerleşik varargs + %s yer tutucu |
| Çıktı kanalları | Yalnızca Logcat | Ağaçlar: Logcat, dosya, Crashlytics, vb. |
| Başlatma olmadan davranış | Her zaman çalışır | Hiçbir şey çıktılamaz |
| Performans | Temel seviye | isLoggable ile tembel biçimlendirme |
Timber'a karşı ana argüman — üçüncü taraf bir kütüphaneye bağımlılık. Minimum loglama ile basit bir proje için Timber kullanımı aşırı olabilir. Ancak, Google Play Console, 2024 verilerine göre, Google Play'deki ilk 1000 uygulamanın %60'ından fazlası Timber kullanmakta olup, bu da güvenilirliğini ve verimliliğini doğrulamaktadır.
Release yapılarında Timber performansı standart Log API ile eşdeğerdir. Hiçbir ağaç dikilmediğinde, Timber.d() metodu ağaçların varlığını kontrol eder (bir if) ve dize biçimlendirme yapmadan geri döner. Bu, her zaman yürütülen birleştirme ile Log.d()'den daha hızlıdır.
Birinci kural — testlerde her zaman Timber başlatmasını kontrol edin. Bir ağacın dikildiğini doğrulamak için Timber.asTree() kullanın. Birim testlerinde, assert kontrolleri için mesajları bir listede saklayan TestTree dikin.
İkinci kural — aynı projede Timber ve android.util.Log'u karıştırmayın. Proje zaten Timber kullanıyorsa, tüm yeni log çağrıları onun üzerinden gitmelidir. Karıştırma, yinelenen mesajlara ve analiz sırasında karışıklığa yol açar.
Üçüncü kural — BuildConfig.DEBUG'u kontrol etmeden CrashReportingTree dikin. DebugTree'nin aksine, crash ağacı hem debug hem de release'de çalışmalıdır — bu, test hatalarının da crash raporlama sistemi tarafından yakalanmasını sağlar.
Dördüncü kural — yerleşik Timber seviyelerini kullanın: Timber.v(), Timber.d(), Timber.i(), Timber.w(), Timber.e(), Timber.wtf(). Sayısal öncelikle doğrudan Timber.log() çağırmaktan kaçının — bu, kod okunabilirliğini azaltır ve yeniden düzenlemeyi zorlaştırır.
Beşinci kural — kütüphaneler ve modüller için Timber.tag("CustomTag") kullanın. Bu metot, genel yapılandırmayı etkilemeden geçersiz kılınmış tag ile geçici bir ağaç döndürür. Bu, özel bir tanımlayıcı ile kütüphane kodundan loglama yapılmasını sağlar.
Sıkça Sorulan Sorular
Evet — Timber kütüphanelerde güvenle kullanılabilir. Uygulamada hiçbir ağaç dikilmezse, Timber çağrıları hata oluşturmaz. Kütüphaneler için, log kaynağını tanımlamak amacıyla Timber.tag("LibraryTag") kullanılması önerilir.
Çağrı yığını (stack trace) aracılığıyla — DebugTree, Timber.d() çağrı noktasından 8 kare yukarı çıkar ve sınıf adını çıkarır. Throwable.stackTrace metodu, Reflection API yükü olmadan çağıran sınıfı belirlemek için kullanılır.
Logcat, logları görüntülemek için bir Android sistem yardımcı programıdır. Timber, log yazmak için bir kütüphanedir. Timber, DebugTree aracılığıyla Logcat'e mesaj gönderir, ancak özel ağaçlar aracılığıyla dosyalara, Crashlytics, Sentry ve diğer kanallara da gönderebilir.
Hayır — Timber, Android SDK'ya (android.util.Log) bağlıdır. KMP projeleri için Kermit veya Napier'i düşünün — benzer ağaç mimarisine sahip, Android, iOS, JVM ve JS'de çalışan çok platformlu loglama kütüphaneleri.
Timber.uprootAll() kullanın — metot kayıtlı tüm ağaçları kaldırır. Timber.uproot(tree) belirli bir ağacı kaldırır. Bu, test metotları arasında durumu sıfırlamak için testlerde kullanışlıdır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun