مستوى التسجيل (Log Level) — تصنيف رسائل التسجيل حسب درجة الأهمية، مما يسمح للمطورين بالتحكم في حجم المعلومات المعروضة في مراحل مختلفة من عمل التطبيق. وفقًا لـ Google Android Developers، 2024، فإن الاختيار الصحيح لمستوى التسجيل يقلل حجم السجلات في الإنتاج بنسبة 85–95% ويسرع تشخيص الأخطاء. كل مستوى يحل مهمته — من التصحيح في مرحلة التطوير إلى مراقبة الأعطال الحرجة في الإنتاج.
النقاط الرئيسية
مستوى التسجيل (Log Level) — سمة لكل رسالة تسجيل تحدد أهميتها وإلحاح معالجتها. تدعم منصات iOS وAndroid الحديثة مقياسًا موحدًا من 6–7 مستويات: من الأكثر تفصيلاً (Verbose/Trace) إلى الحرج (Error/Assert). يحدد اختيار المستوى ما إذا كانت الرسالة ستُكتب في السجل بالتكوين الحالي للتطبيق.
يعتمد مفهوم مستوى التسجيل على مبدأ هرم الأهمية: كلما ارتفع المستوى، قل عدد الرسائل المعروضة عليه. وفقًا لـ Semaphore CI، 2024، في تطبيق إنتاجي يكون التوزيع كالتالي: Info — 60% من الرسائل، Warn — 25%، Error — 10%، Debug — 5%. يجب تعطيل رسائل Verbose تمامًا في الإنتاج.
تنفذ كل منصة مستوى التسجيل من خلال واجهة برمجية خاصة بها. يستخدم Android android.util.Log بالطرق v(), d(), i(), w(), e(). تستخدم Apple OSLog بالمستويات default, info, debug, error, fault. تضيف مكتبات مثل Timber وCocoaLumberjack وظائف إضافية فوق هذه الواجهات البرمجية القياسية.
وفقًا لـ Google I/O 2023، الاختيار غير الصحيح لمستوى التسجيل هو سبب 40% من مشكلات الأداء في الإنتاج. يترك المطورون سجلات Debug في إصدارات الإصدار، مما يؤدي إلى كتابة مفرطة على القرص واستنزاف متسارع للبطارية.
Verbose (TRACE) — المستوى الأكثر تفصيلاً، المخصص حصريًا للتطوير. في هذا المستوى، يتم عرض جميع الحسابات الوسيطة وتكرارات الحلقات ونتائج كل خطوة من الخوارزمية. في Android، يتوافق هذا المستوى مع Log.v()، في iOS — OSLog من النوع debug (قبل iOS 14 كان يُستخدم os_trace).
Debug — رسائل تصحيح مفيدة أثناء التطوير والاختبار. تحتوي على معلومات حول حالة الكائنات الرئيسية ونتائج استعلامات SQL ومعلمات استدعاءات API. على عكس Verbose، رسائل Debug منظمة وذات دلالة معنوية. في iOS، يتوافق هذا المستوى مع OSLogType.debug.
Info — رسائل إعلامية عن الأحداث العادية للتطبيق: تهيئة SDK، مصادقة ناجحة، فتح شاشة، استلام بيانات من الخادم. يجب ألا تحتوي رسائل Info على بيانات شخصية للمستخدمين ويجب أن تكون آمنة للتحليل في الإنتاج. في iOS يُستخدم OSLogType.info، في Android — Log.i().
Warn — تحذيرات حول مشكلات محتملة. يستمر التطبيق في العمل، لكن الموقف يتطلب انتباهًا: حجم ذاكرة التخزين المؤقت يقترب من الحد الأقصى، إصدار API قديم، استجابة شبكة بطيئة، إعادة محاولة الاتصال. في Android — Log.w()، في iOS — OSLogType.default (للتحذيرات).
Error — أخطاء حرجة حيث لا يمكن للتطبيق تنفيذ العملية المطلوبة لكنه يستمر في العمل: طلب API فاشل، فقدان الاتصال، خطأ في كتابة قاعدة البيانات، نقص الأذونات. في iOS، يُستخدم OSLogType.error للأخطاء، في Android — Log.e().
Assert (WTF) — أعلى مستوى، يشير إلى موقف «لا يمكن أن يحدث.» يُستخدم لتسجيل الأخطاء التي تنتهك الثوابت الأساسية للنظام. في Android، لا تظهر رسائل Assert في إصدارات الإصدار افتراضيًا. في iOS، يتم التعامل مع WTF (What a Terrible Failure) من خلال OSLogType.fault.
Android Log API — آلية التسجيل المضمنة من حزمة android.util.Log. توفر 6 طرق ثابتة: Log.v(), Log.d(), Log.i(), Log.w(), Log.e() وLog.wtf(). تأخذ كل طريقة tag (سلسلة تعريف المصدر) وmsg (نص الرسالة).
class UserRepository {
companion object {
private val TAG = "UserRepo"
}
suspend fun loadUser(id: String): User {
Log.d(TAG, "جاري تحميل المستخدم بالمعرف: $id")
return try {
val response = api.fetchUser(id)
Log.i(TAG, "تم تحميل المستخدم بنجاح")
response.toUser()
} catch (e: Exception) {
Log.e(TAG, "فشل تحميل المستخدم: ${e.message}")
throw e
}
}
}
التصفية حسب المستويات في Android Logcat تتم عبر ADB: adb logcat *:E سيظهر رسائل Error فقط. في إصدارات الإنتاج، تتم إزالة جميع استدعاءات Log.v() وLog.d() بواسطة ProGuard/R8 عند تمكين التصغير. تبقى Log.i() وLog.w() وLog.e()، لذلك من المهم عدم إخراج بيانات حساسة من خلال هذه الطرق.
للتصفية المخصصة في وقت التشغيل، يوفر Android Log.isLoggable(tag, level) — طريقة تتحقق مما إذا كان المستوى المحدد مفعلًا للtag المعطى. يتيح ذلك تمكين التسجيل التفصيلي ديناميكيًا لوحدة معينة دون إعادة بناء التطبيق.
OSLog — نظام التسجيل الموحد من Apple، الذي حل محل NSLog القديم. يوفر OSLog 5 مستويات: debug, info, default (notice), error وfault. الميزة الرئيسية هي التسجيل المهيكل مع دعم السلاسل المنسقة والتصفية الديناميكية عبر وحدة التحكم.
import OSLog
let logger = Logger(
subsystem: "com.example.app",
category: "network"
)
func fetchData(from url: URL) {
logger.debug("Starting request to \(url.absoluteString)")
do {
let data = try Data(contentsOf: url)
logger.info("Received \(data.count) bytes")
} catch {
logger.error("Request failed: \(error.localizedDescription)")
}
}
نظام التصفية لـ OSLog يعمل على مستوى نظام التشغيل. تتم كتابة رسائل Debug فقط عند توصيل المصحح أو عند تمكين الوسيطة -com.apple.CoreData.Logging.debug 1. تُجمع رسائل Info في ذاكرة الجهاز (حتى 512 كيلوبايت) ويمكن الوصول إليها عبر Console.app. تُكتب رسائل Error وfault باستمرار وتكون متاحة للتجميع عبر أنظمة الإبلاغ عن الأعطال.
ميزة مهمة لـ OSLog: السلاسل المنسقة مع عناصر نائبة. بدلاً من استيفاء سلاسل Swift (التي تُحسَب دائمًا، بغض النظر عن المستوى)، يستخدم OSLog تنسيق os_log مع %{public}@ و%{private}@ للتمييز بين البيانات الحساسة. يتم إخفاء المعلمات الخاصة في سجلات الإنتاج.
القاعدة الرئيسية — مجموعة دنيا من المستويات في الإنتاج: Info، Warn، Error، Assert. يجب تعطيل Debug وVerbose. السبب ليس الأمان بقدر ما هو الأداء: كل استدعاء تسجيل يستهلك وقت معالج لتنسيق السلسلة، حتى إذا لم يتم عرض الرسالة.
تحسين حرج — لا تستخدم أبدًا استيفاء السلاسل في استدعاءات التسجيل. إذا تم بناء السلسلة قبل استدعاء log()، يُهدر وقت المعالج حتى عند تعطيل المستوى. استخدم التنسيق البطيء عبر لامبدا أو شروط الحراسة.
في Android، يخدم الطريقة Log.isLoggable() هذا الغرض؛ في OSLog، يتم دعم السلاسل المنسقة الأصلية مع عناصر نائبة. يحل Timber لمشكلة Android من خلال timber.log.Tree مع التحقق من المستوى داخل الشجرة.
مستوى التسجيل عن بُعد — ممارسة يتم فيها التحكم في مستوى التسجيل من الخادم عبر Firebase Remote Config أو خدمة مماثلة. إذا حدث خطأ معقد في الإنتاج، يمكن للمطور تمكين تسجيل Debug عن بُعد لوحدة معينة على أجهزة مجموعة مختارة من المستخدمين.
وفقًا لـ Firebase، 2024، تقلل هذه الممارسة وقت تشخيص الأخطاء النادرة بنسبة 60% وتتيح الحصول على صورة كاملة للمشكلة دون تثبيت إصدار تصحيح. القيد الرئيسي — يتم تمكين التسجيل فقط عند بدء التشغيل التالي للتطبيق بعد استلام التكوين.
BuildConfig.DEBUG في Android و#if DEBUG في Swift — آليات الترجمة الشرطية القياسية التي تعطل مستويات التصحيح في إصدارات الإصدار. للهندسة النظيفة، يُوصى بنقل اختيار مستوى التسجيل إلى حاوية DI أو مصنع مسجلات لتجنب ازدحام منطق الأعمال بالتوجيهات الشرطية.
القاعدة الأولى — يجب أن يجيب كل استدعاء تسجيل على السؤال «من، ماذا، متى.» من — المكون أو الوحدة (tag في Android، category في iOS). ماذا — الحدث المحدد أو تغيير الحالة. متى — الطابع الزمني، الذي يضاف تلقائيًا بواسطة نظام التسجيل.
القاعدة الثانية — لا تسجل بيانات حساسة من خلال Info وما فوق. كلمات المرور، الرموز، البريد الإلكتروني، أرقام الهواتف، الإحداثيات الجغرافية الدقيقة — ممنوعة منعًا باتًا في أي سجل يصل إلى الإنتاج. إذا لزم الأمر، استخدم الإخفاء: «email: us***@example.com.»
القاعدة الثالثة — مستوى Warn هو مسؤولية المطور، Error — مسؤولية الفريق. Warn تعني «هنا مشكلة محتملة، راقبها.» Error تعني «هنا مشكلة، أصلحها.» لا تستخدم Error للمواقف المتوقعة والمعالجة (مثل خطأ API 404).
القاعدة الرابعة — الاتساق. يجب أن يستخدم المشروع بأكمله اتفاقيات تسمية موحدة للtags والفئات. يُوصى باستخدام ClassName.methodName لtags Android وmodule.subsystem لفئات iOS. يتيح ذلك تصفية سريعة للسجلات حسب المكون.
القاعدة الخامسة — اختبر سجلاتك. في اختبارات الوحدة، تحقق من استدعاء مستوى التسجيل الصحيح في سيناريوهات محددة. توجد مكتبات mock للتسجيل لهذا الغرض: Mockito لـ Android، Cuckoo لـ iOS. يمنع التحقق من المستويات في الاختبارات تسرب رسائل التصحيح إلى الإنتاج.
الأسئلة الشائعة
استنزاف متسارع للبطارية وكتابة مفرطة على القرص. كل سجل Debug ينسق سلسلة ويكتب بيانات في المخزن المؤقت. على الأجهزة ذات ذاكرة Flash، يسرع ذلك تآكل التخزين. بالإضافة إلى ذلك، قد تحتوي سجلات Debug على بيانات حساسة غير مخصصة للعرض في الإنتاج.
Debug — لجسم الطلب والاستجابة والرؤوس ورمز الحالة. Info — لحقيقة تنفيذ الطلب (URL، الطريقة، المدة). Error — للطلبات الفاشلة برموز 4xx/5xx. لا تستخدم أبدًا Verbose لسجلات الشبكة في الإنتاج.
OSLogType.default (مستوى notice) — رسائل متوسطة الأهمية، تُحفظ في سجل النظام وتكون مرئية في Console.app. OSLogType.info — رسائل تقنية، لا تُحفظ بشكل دائم، متاحة فقط أثناء التنميط النشط عبر Instruments.
R8/ProGuard يزيل Log.v() وLog.d() عند تمكين التصغير في إصدارات الإصدار. تبقى Log.i() وLog.w() وLog.e(). للإزالة الكاملة لجميع السجلات، يلزم قاعدة مخصصة -assumenosideeffects class android.util.Log مع تحديد جميع المستويات.
لا — التسجيل المفرط يضعف قابلية القراءة والأداء. سجل الدخول فقط في الطرق المعقدة أو غير المتزامنة. للطرق المتزامنة، يكفي سجل واحد عند نقطة الإرجاع أو الخطأ. استخدم مستوى Debug لتتبع الاستدعاءات.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا