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 with Trees) آرکیٹیکچرل پیٹرن پر بنائی گئی ہے۔ مقررہ رویے کے ساتھ ایک واحد 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.Tree۔ Timber ایک facade کے طور پر کام کرتا ہے جو ہر لاگ کال کو لگائے گئے تمام درختوں کو سونپتا ہے۔ ہر درخت فیصلہ کرتا ہے کہ پیغام پر کارروائی کرنی ہے یا نہیں، اور اگر ہاں تو اسے کہاں بھیجنا ہے۔
DebugTree لائبریری کے ساتھ شامل معیاری Tree نفاذ ہے۔ یہ کال اسٹیک کا تجزیہ کرکے tag کا تعین کرتا ہے: یہ Timber.d() کال پوائنٹ سے 8 فریم اوپر جاتا ہے اور اس کلاس کا نام ڈھونڈتا ہے جس نے لاگ میتھڈ کو بلایا تھا۔ DebugTree خود بخود غیر فعال ہو جاتا ہے (کچھ آؤٹ پٹ نہیں کرتا) release بلڈز میں کیونکہ یہ BuildConfig.DEBUG چیک کرتا ہے۔
Forest (جنگل) — لگائے گئے تمام درختوں کا مجموعہ۔ جب Timber.d("پیغام") میتھڈ بلایا جاتا ہے، لائبریری پیغام کو لگانے کی ترتیب میں تمام درختوں کو بار بار منتقل کرتی ہے۔ ہر درخت پیغام کو سطح، tag یا مواد کے مطابق فلٹر کر سکتا ہے اور اپنے طریقے سے پروسیس کر سکتا ہے۔
لگانے کی ترتیب اہم ہے: پہلا لگایا گیا درخت پہلے پروسیس ہوتا ہے۔ یہ سفارش کی جاتی ہے کہ DebugTree کو آخ میں لگائیں، تاکہ کسٹم درخت (مثلاً Crashlytics) پیغام کو Logcat تک پہنچنے سے پہلے پروسیس کر لیں۔
Timber تھریڈ سیف ہے — تمام میتھڈز اندرونی لاک کے ذریعے ہم آہنگ (synchronized) ہیں۔ یہ اس بات کی ضمانت دیتا ہے کہ مختلف تھریڈز کے پیغامات آپس میں نہیں ملیں گے۔ تاہم، کسٹم درخت کے اندر، ہم آہنگی ڈیولپر کی ذمہ داری ہے: اگر درخت فائل میں لکھتا ہے تو 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")
}
}
تنصیب 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 استعمال کرتی ہیں، جو اس کی وشوسنییتا اور کارکردگی کی تصدیق کرتی ہے۔
Release بلڈز میں 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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں