Timber Android के लिए एक हल्की लॉगिंग लाइब्रेरी है जिसमें ट्री (Tree) आधारित विस्तार योग्य आर्किटेक्चर है, जिसने हजारों प्रोजेक्ट्स में मानक android.util.Log को बदल दिया है। GitHub, 2024 के अनुसार, लाइब्रेरी ने 10,000 से अधिक स्टार प्राप्त किए हैं और इसका उपयोग 1 बिलियन से अधिक इंस्टॉल वाले ऐप्स में किया जाता है। Timber Log API की तीन मुख्य समस्याओं को हल करता है: स्वचालित tag की कमी, अनिवार्य isLoggable जांच, और कॉल की स्थिर प्रकृति।
मुख्य बिंदु
Timber Android के लिए एक ओपन-सोर्स लाइब्रेरी है जिसे Jake Wharton ने 2013 में मानक android.util.Log के विकल्प के रूप में बनाया था। Timber का मुख्य विचार अनिवार्य मैन्युअल tag के साथ स्थिर Log API को एक स्वचालित तंत्र से बदलना है जो स्टैक के माध्यम से कॉल स्रोत निर्धारित करता है।
लाइब्रेरी पेड़ों के साथ Composite आर्किटेक्चरल पैटर्न पर बनाई गई है। एकल निश्चित व्यवहार वाले Log क्लास के बजाय, Timber पेड़ों का एक "जंगल" प्रबंधित करता है — प्रत्येक पेड़ अपने स्वयं के आउटपुट चैनल के लिए जिम्मेदार है: कंसोल, फ़ाइल, Crashlytics, रिमोट सर्वर। डेवलपर किसी भी संख्या में पेड़ जोड़ सकता है और उन्हें संयोजित कर सकता है।
Google I/O 2019 के अनुसार, Google द्वारा Timber को Android ऐप्स में लॉगिंग के लिए सर्वोत्तम अभ्यास के रूप में अनुशंसित किया गया है। लाइब्रेरी APK में 10 KB से कम जगह लेती है और इसकी कोई बाहरी निर्भरता नहीं है, जो इसे किसी भी पैमाने के प्रोजेक्ट्स के लिए आदर्श विकल्प बनाता है।
Timber बड़ी टीमों में असंगत tag की समस्या को हल करता है। जब प्रत्येक डेवलपर मैन्युअल रूप से tag लिखता है, तो टाइपो और विसंगतियां अपरिहार्य हैं — एक क्लास "MainActivity" के रूप में लॉग होती है, दूसरी "MAIN_ACTIVITY" के रूप में। Timber स्वचालित रूप से क्लास नाम से tag निकालता है: MainActivity.kt → tag MainActivity।
आर्किटेक्चर Timber में दो घटक होते हैं: केंद्रीय स्थिर क्लास Timber और अमूर्त क्लास Timber.Tree। Timber एक फ़ेसाड के रूप में कार्य करता है जो प्रत्येक लॉग कॉल को सभी लगाए गए पेड़ों को सौंपता है। प्रत्येक पेड़ तय करता है कि संदेश को संसाधित करना है या नहीं, और यदि हां, तो इसे कहां भेजना है।
DebugTree लाइब्रेरी के साथ शामिल मानक Tree कार्यान्वयन है। यह कॉल स्टैक का विश्लेषण करके tag निर्धारित करता है: यह Timber.d() कॉल बिंदु से 8 फ्रेम ऊपर जाता है और उस क्लास का नाम ढूंढता है जिसने लॉग विधि को बुलाया। DebugTree रिलीज़ बिल्ड में स्वचालित रूप से अक्षम हो जाता है (कुछ भी आउटपुट नहीं करता) क्योंकि यह BuildConfig.DEBUG की जांच करता है।
Forest (जंगल) — सभी लगाए गए पेड़ों का संग्रह। जब Timber.d("message") विधि कॉल की जाती है, तो लाइब्रेरी संदेश को उनके लगाए जाने के क्रम में सभी पेड़ों को पुनरावृत्त रूप से पास करती है। प्रत्येक पेड़ संदेश को स्तर, tag या सामग्री के आधार पर फ़िल्टर कर सकता है और अपने तरीके से संसाधित कर सकता है।
लगाने का क्रम मायने रखता है: पहला लगाया गया पेड़ पहले संसाधित होता है। DebugTree को अंत में लगाने की सिफारिश की जाती है, ताकि कस्टम पेड़ (जैसे Crashlytics) Logcat तक पहुंचने से पहले संदेश को संसाधित कर सकें।
Timber थ्रेड-सेफ है — सभी विधियां आंतरिक लॉक के माध्यम से सिंक्रनाइज़ हैं। यह गारंटी देता है कि विभिन्न थ्रेड्स के संदेश मिश्रित नहीं होंगे। हालांकि, कस्टम पेड़ के अंदर, सिंक्रनाइज़ेशन डेवलपर की जिम्मेदारी है: यदि पेड़ फ़ाइल में लिखता है, तो synchronized या ReentrantLock का उपयोग किया जाना चाहिए।
// 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")
}
}
स्थापना Timber की build.gradle में एकल निर्भरता जोड़कर की जाती है। लाइब्रेरी Maven Central पर com.jakewharton.timber:timber आर्टिफैक्ट के तहत प्रकाशित है। 2024 तक वर्तमान संस्करण 5.0.1 है, नवीनतम स्थिर अद्यतन।
// build.gradle (Module: app)
dependencies {
implementation 'com.jakewharton.timber:timber:5.0.1'
}
स्थापना के बाद न्यूनतम सेटअप — Application.onCreate में DebugTree लगाना। इस चरण के बिना, Timber बिना कोई अपवाद फेंके सभी लॉग कॉल को अनदेखा करेगा। यह सुरक्षित डिफ़ॉल्ट व्यवहार है: यदि कोई पेड़ नहीं लगाया गया है, तो लाइब्रेरी न्यूनतम ओवरहेड के साथ निष्क्रिय चलती है।
Jake Wharton, 2023 के अनुसार, नए उपयोगकर्ताओं के लिए 70% Timber समस्याएं भूली या गलत आरंभीकरण से संबंधित हैं। जब कोई पेड़ नहीं होता है तो Timber कोई त्रुटि उत्पन्न नहीं करता है — डेवलपर्स Logcat में लॉग दिखाई देने की उम्मीद करते हैं, लेकिन कुछ नहीं होता है।
परीक्षण के लिए, Timber Timber.asTree() प्रदान करता है — एक विधि जो वर्तमान पेड़ या null लौटाती है। यह यूनिट परीक्षणों के लिए सुविधाजनक है: आप पेड़ को mock से बदल सकते हैं और सत्यापित कर सकते हैं कि लॉग संदेश सही स्तर और tag के साथ भेजा गया था।
कस्टम पेड़ — मानक Log API के बजाय Timber का उपयोग करने का मुख्य कारण। Tree विधियों को ओवरराइड करके, आप किसी भी स्तर के लॉग को Crashlytics, फ़ाइल सिस्टम, Remote Config या अपने स्वयं के सर्वर पर रूट कर सकते हैं।
class CrashReportingTree : Timber.Tree() {
override fun isLoggable(tag: String?, priority: Int): Boolean {
// क्रैश-रिपोर्टिंग के लिए केवल Error और 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")
}
}
}
ओवरराइड करने के लिए विधियां: isLoggable(tag, priority) — एक फ़िल्टर जो निर्धारित करता है कि संदेश को संसाधित करना है या नहीं (आधार कार्यान्वयन true लौटाता है)। log(priority, tag, message, t) — मुख्य प्रसंस्करण तर्क। prepareLog(priority, tag, throwable, message, args) — फ़ॉर्मेटिंग से पहले बुलाया जाता है, संदेश को संसाधित करने से पहले संशोधित करने की अनुमति देता है।
कस्टम पेड़ों का एक महत्वपूर्ण लाभ कोई रिफ्लेक्शन नहीं है। कई लॉगिंग फ्रेमवर्क के विपरीत, Timber tag या स्तर निर्धारित करने के लिए Reflection API का उपयोग नहीं करता है। Tag कॉल स्टैक (Throwable.stackTrace) के विश्लेषण के माध्यम से गणना की जाती है, जो कई गुना तेज काम करता है।
तुलना Timber और मानक Log API की चार मुख्य अंतर दिखाती है: स्वचालित tag, varargs के साथ स्ट्रिंग फ़ॉर्मेटिंग समर्थन, एकाधिक आउटपुट चैनल, और आरंभीकरण के बिना सुरक्षित व्यवहार।
| पैरामीटर | android.util.Log | Timber |
|---|---|---|
| Tag पहचान | मैन्युअल, स्ट्रिंग स्थिरांक | स्वचालित, कॉल स्टैक के माध्यम से |
| फ़ॉर्मेटिंग | कॉन्केटनेशन या String.format | अंतर्निहित varargs + %s प्लेसहोल्डर |
| आउटपुट चैनल | केवल Logcat | पेड़: Logcat, फ़ाइल, Crashlytics, आदि |
| आरंभीकरण के बिना व्यवहार | हमेशा काम करता है | कुछ भी आउटपुट नहीं करता |
| प्रदर्शन | आधार स्तर | isLoggable के माध्यम से आलसी फ़ॉर्मेटिंग |
Timber के खिलाफ मुख्य तर्क — तीसरे पक्ष की लाइब्रेरी पर निर्भरता। न्यूनतम लॉगिंग वाले सरल प्रोजेक्ट के लिए, Timber का उपयोग अत्यधिक हो सकता है। हालांकि, Google Play Console, 2024 के अनुसार, Google Play पर शीर्ष 1000 ऐप्स में से 60% से अधिक Timber का उपयोग करते हैं, जो इसकी विश्वसनीयता और दक्षता की पुष्टि करता है।
रिलीज़ बिल्ड में Timber प्रदर्शन मानक Log API के बराबर है। जब कोई पेड़ नहीं लगाया गया है, तो Timber.d() विधि पेड़ों की उपस्थिति की जांच करती है (एक if) और लौटती है — बिना स्ट्रिंग फ़ॉर्मेटिंग के। यह Log.d() से तेज है जो हमेशा निष्पादित होता है।
पहला नियम — परीक्षणों में हमेशा Timber आरंभीकरण की जांच करें। यह सत्यापित करने के लिए Timber.asTree() का उपयोग करें कि पेड़ लगाया गया है। यूनिट परीक्षणों में, TestTree लगाएं जो assert जांच के लिए संदेशों को सूची में सहेजता है।
दूसरा नियम — एक ही प्रोजेक्ट में Timber और android.util.Log को न मिलाएं। यदि प्रोजेक्ट पहले से Timber का उपयोग करता है, तो सभी नए लॉग कॉल उसके माध्यम से जाने चाहिए। मिश्रण से डुप्लिकेट संदेश और विश्लेषण के दौरान भ्रम होता है।
तीसरा नियम — BuildConfig.DEBUG की जांच किए बिना CrashReportingTree लगाएं। DebugTree के विपरीत, क्रैश पेड़ को debug और release दोनों में काम करना चाहिए — यह सुनिश्चित करता है कि परीक्षण त्रुटियां भी क्रैश-रिपोर्टिंग सिस्टम द्वारा कैप्चर की जाती हैं।
चौथा नियम — अंतर्निहित Timber स्तरों का उपयोग करें: Timber.v(), Timber.d(), Timber.i(), Timber.w(), Timber.e(), Timber.wtf()। संख्यात्मक प्राथमिकता के साथ सीधे Timber.log() को कॉल करने से बचें — इससे कोड पठनीयता कम होती है और रीफैक्टरिंग जटिल होती है।
पाँचवाँ नियम — लाइब्रेरी और मॉड्यूल के लिए, Timber.tag("CustomTag") का उपयोग करें। यह विधि वैश्विक कॉन्फ़िगरेशन को प्रभावित किए बिना ओवरराइड tag के साथ एक अस्थायी पेड़ लौटाती है। यह कस्टम पहचानकर्ता के साथ लाइब्रेरी कोड से लॉगिंग की अनुमति देता है।
अक्सर पूछे जाने वाले प्रश्न
हाँ — Timber लाइब्रेरी में उपयोग करना सुरक्षित है। यदि एप्लिकेशन में कोई पेड़ नहीं लगाया गया है, तो Timber कॉल त्रुटियां नहीं फेंकती हैं। लाइब्रेरी के लिए, लॉग स्रोत की पहचान करने के लिए Timber.tag("LibraryTag") का उपयोग करने की अनुशंसा की जाती है।
कॉल स्टैक (stack trace) के माध्यम से — DebugTree Timber.d() कॉल बिंदु से 8 फ्रेम ऊपर जाता है और क्लास नाम निकालता है। Throwable.stackTrace विधि का उपयोग Reflection API ओवरहेड के बिना कॉल करने वाले क्लास को निर्धारित करने के लिए किया जाता है।
Logcat लॉग देखने के लिए एक Android सिस्टम उपयोगिता है। Timber लॉग लिखने के लिए एक लाइब्रेरी है। Timber DebugTree के माध्यम से Logcat को संदेश भेजता है, लेकिन कस्टम पेड़ों के माध्यम से उन्हें फ़ाइलों, Crashlytics, Sentry और अन्य चैनलों पर भी भेज सकता है।
नहीं — Timber Android SDK (android.util.Log) से बंधा है। KMP प्रोजेक्ट्स के लिए, Kermit या Napier पर विचार करें — समान पेड़ आर्किटेक्चर वाली मल्टीप्लेटफ़ॉर्म लॉगिंग लाइब्रेरी, जो Android, iOS, JVM और JS पर काम करती हैं।
Timber.uprootAll() का उपयोग करें — यह विधि सभी पंजीकृत पेड़ों को हटा देती है। Timber.uproot(tree) एक विशिष्ट पेड़ को हटाता है। यह परीक्षण विधियों के बीच स्थिति रीसेट करने के लिए परीक्षणों में उपयोगी है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें