واجهة SLF4J والمسجلات
سجّل بالمستوى المناسب
واجهة SLF4J والمسجلات درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
ما هي SLF4J؟
إن SLF4J (Simple Logging Facade for Java) هي طبقة تجريد. تكتبون الكود اعتمادًا على واجهة برمجة التطبيقات الخاصة بها، بينما تتولى واجهة خلفية مثل Logback أو Log4j2 تنفيذ التسجيل الفعلي.
يتيح ذلك للمكتبات تسجيل الأحداث دون فرض تطبيق محدد على التطبيق.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("Application started");
}
}الحصول على مسجّل
أنشئوا مسجّلًا واحدًا لكل صنف باستخدام LoggerFactory.getLogger(MyClass.class).
وفقًا للعرف، يكون الحقل private static final ويُسمى log أو logger. ويصبح الصنف اسم المسجّل، الذي يظهر في المخرجات.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OrderService {
private static final Logger log = LoggerFactory.getLogger(OrderService.class);
void placeOrder(String id) {
log.info("Placing order {}", id);
}
}المستويات الخمسة
توفّر مسجّلات SLF4J طريقة واحدة لكل مستوى:
log.trace(...)log.debug(...)log.info(...)log.warn(...)log.error(...)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.trace("entering main");
log.debug("args length = {}", args.length);
log.info("service is up");
log.warn("cache miss");
log.error("failed to connect");
}
}اختيار المستوى المناسب
الإرشادات:
- ERROR: فشل حقيقي يجب على شخص مراجعته.
- WARN: حالة غير اعتيادية يمكن التعافي منها.
- INFO: أحداث مهمة في دورة حياة التطبيق.
- DEBUG: معلومات تشخيصية للمطورين، وتكون معطّلة في بيئة الإنتاج.
- TRACE: تتبّع مفصل للغاية.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PaymentService {
private static final Logger log = LoggerFactory.getLogger(PaymentService.class);
void charge(int cents) {
if (cents <= 0) { log.warn("non-positive charge: {}", cents); return; }
log.info("charged {} cents", cents);
}
}أسماء المسجّلات وتسلسلها الهرمي
تكون أسماء المسجّلات هرمية وفق الحزم المفصولة بنقاط. ويكون المسجّل المسمى com.example.svc تابعًا لـ com.example.
ينطبق الإعداد على مسجّل الأصل وأبنائه ما لم يُتجاوز، ولذلك يمكنكم تعيين مستويات لكل حزمة.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
public static void main(String[] args) {
Logger a = LoggerFactory.getLogger("com.example.app");
Logger b = LoggerFactory.getLogger("com.example.app.db");
a.info("parent logger");
b.debug("child inherits parent's level unless overridden");
}
}حماية الاستدعاءات المكلفة
عند إنشاء رسالة مكلفة، استخدموا isDebugEnabled() للتحقق من المستوى، بحيث لا تُنفَّذ العملية إلا عندما يكون المستوى مفعّلًا.
مع التسجيل ذي المعلمات (في الدرس التالي)، نادرًا ما تحتاجون إلى ذلك، لكنه ضروري عند إنشاء السلاسل النصية بأنفسكم.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String heavyDump() { return "...large state..."; }
public static void main(String[] args) {
if (log.isDebugEnabled()) {
log.debug("state: {}", heavyDump());
}
}
}تسجيل الاستثناءات
لتسجيل استثناء مع تتبّع مكدس الاستدعاءات كاملًا، مرّروا Throwable باعتباره المعامل الأخير.
لا تضعوا الاستثناء في عنصر نائب؛ بل مرّروه بعد الرسالة.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
try {
throw new IllegalStateException("boom");
} catch (Exception e) {
log.error("Operation failed for id {}", 42, e);
}
}
}مسجّل واحد لكل صنف
صرّحوا عن المسجّل مرة واحدة باعتباره حقلًا ثابتًا ونهائيًا. لا تنشئوا مسجّلًا داخل طريقة أبدًا، لأن ذلك يهدر العمل ويضيّع فائدة اسم الصنف.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserRepository {
// Good: one shared logger named after the class
private static final Logger log = LoggerFactory.getLogger(UserRepository.class);
void save(String user) { log.debug("saving {}", user); }
}SLF4J مقارنةً بالواجهة الخلفية
إن SLF4J ليست سوى واجهة برمجة التطبيقات. وعند التشغيل، ترتبط بأي واجهة خلفية موجودة في مسار الأصناف.
- أضيفوا
logback-classic: عندها تستخدم SLF4J واجهة Logback الخلفية. - أضيفوا
log4j-slf4j2-impl: عندها تستخدم SLF4J واجهة Log4j2 الخلفية.
لا يتغير كودكم مطلقًا.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
// Same code, different backend depending on classpath
log.info("backend-agnostic logging");
}
}تجنبوا تسجيل البيانات الحساسة
لا تسجلوا كلمات المرور أو الرموز المميزة أو أرقام بطاقات الائتمان كاملةً مطلقًا. غالبًا ما تُرسل السجلات إلى أنظمة عديدة ويُحتفظ بها لفترة طويلة.
أخفوا الحقول الحساسة أو احذفوها قبل التسجيل.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
static String mask(String card) { return "****" + card.substring(card.length() - 4); }
public static void main(String[] args) {
log.info("charged card {}", mask("4111111111111234"));
}
}خدمة واقعية
بتجميع كل ما سبق، نرى خدمة صغيرة تسجل الأحداث بالمستويات المناسبة وتتضمن مسارًا لمعالجة الاستثناءات.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EmailService {
private static final Logger log = LoggerFactory.getLogger(EmailService.class);
void send(String to) {
log.debug("preparing email to {}", to);
try {
if (to == null) throw new IllegalArgumentException("null recipient");
log.info("email sent to {}", to);
} catch (Exception e) {
log.error("failed to send email", e);
}
}
}اختبار سريع
اختبروا أساسيات SLF4J لديكم.
مراجعة
لقد تعلمتم واجهة SLF4J التجريدية:
- احصلوا على
private static final Loggerواحد لكل صنف. - استخدموا طرق المستويات الخمسة بما يناسب.
- أسماء المسجّلات هرمية للتحكم على مستوى الحزمة.
- مرّروا
Throwableأخيرًا لتسجيل تتبّع مكدس الاستدعاءات، ولا تسجلوا الأسرار مطلقًا.
في الدرس التالي، سنتناول الرسائل ذات المعلمات الفعّالة.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Main {
private static final Logger log = LoggerFactory.getLogger(Main.class);
public static void main(String[] args) {
log.info("SLF4J facade recap complete");
}
}الأسئلة الشائعة
هل درس «واجهة SLF4J والمسجلات» مجاني؟
نعم — نص درس «واجهة SLF4J والمسجلات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «واجهة SLF4J والمسجلات»؟
سجّل بالمستوى المناسب تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «واجهة SLF4J والمسجلات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- لماذا التسجيل المنظّم
- واجهة SLF4J والمسجلات
- التسجيل المعلَّم بالمعلمات
- تهيئة Logback