لماذا التسجيل المنظّم
ما بعد System.out.println
لماذا التسجيل المنظّم درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.
مشكلة println
يُعد System.out.println مناسبًا لتجربة سريعة، لكنه أداة تسجيل ضعيفة للتطبيقات الحقيقية.
- لا يوفر الطوابع الزمنية أو المستويات أو أسماء سلاسل التنفيذ.
- لا توجد طريقة لإيقافه في بيئة الإنتاج.
- يكتب إلى stdout فقط، من دون توجيه للمخرجات.
public class Main {
public static void main(String[] args) {
// Crude: no level, no timestamp, always on
System.out.println("User logged in");
}
}ما الذي تضيفه أطر التسجيل؟
يوفر إطار التسجيل ما يلي:
- المستويات (TRACE وDEBUG وINFO وWARN وERROR) لتصفية الضوضاء.
- الطوابع الزمنية وأسماء سلاسل التنفيذ والمسجّلات تلقائيًا.
- التوجيه إلى الملفات أو وحدة التحكم أو الأنظمة البعيدة.
- إعدادًا وقت التشغيل من دون إعادة التصريف.
public class Main {
public static void main(String[] args) {
// A framework would render: time, level, logger, thread, message
String simulated = "2026-01-01 10:00:00 INFO c.e.App [main] - User logged in";
System.out.println(simulated);
}
}شرح مستويات السجل
ترتّب المستويات الرسائل حسب أهميتها:
- TRACE: تفاصيل دقيقة جدًا.
- DEBUG: معلومات تشخيصية أثناء التطوير.
- INFO: المحطات العادية.
- WARN: أمر غير متوقع، لكن يمكن التعافي منه.
- ERROR: فشل يحتاج إلى الانتباه.
public class Main {
enum Level { TRACE, DEBUG, INFO, WARN, ERROR }
public static void main(String[] args) {
Level threshold = Level.INFO;
for (Level l : Level.values()) {
boolean shown = l.ordinal() >= threshold.ordinal();
System.out.println(l + " visible? " + shown);
}
}
}التصفية حسب الحد
يمتلك المسجّل حدًا. وتُهمَل الرسائل الأدنى من هذا الحد بتكلفة منخفضة.
قد تضبطون في بيئة الإنتاج المستوى INFO، فتختفي رسائل DEBUG وTRACE، مما يقلل الضوضاء والتكلفة من دون تغيير الشيفرة.
public class Main {
enum Level { TRACE, DEBUG, INFO, WARN, ERROR }
static void log(Level threshold, Level level, String msg) {
if (level.ordinal() >= threshold.ordinal()) {
System.out.println(level + " - " + msg);
}
}
public static void main(String[] args) {
Level t = Level.WARN;
log(t, Level.DEBUG, "hidden detail");
log(t, Level.ERROR, "shown error");
}
}السجلات المهيكلة وغير المهيكلة
السجلات غير المهيكلة عبارة عن جمل عادية. أما السجلات المهيكلة فتُرفق بها معلومات سياقية على شكل أزواج مفتاح-قيمة، مثل معرّف المستخدم ومعرّف الطلب، ويمكن للآلات تحليلها.
يمكن البحث في السجلات المهيكلة وتجميعها باستخدام أدوات مثل Elasticsearch أو Loki.
import java.util.Map;
public class Main {
public static void main(String[] args) {
// Structured context as key-value pairs
Map<String, Object> fields = Map.of("event", "login", "userId", 42, "ok", true);
System.out.println(fields);
}
}فكرة الواجهة الوسيطة
ينبغي ألا تربطوا شيفرتكم بمكتبة تسجيل محددة. تتيح لكم واجهة وسيطة مثل SLF4J البرمجة باستخدام واجهة API واحدة، ثم تبديل الواجهة الخلفية، مثل Logback أو Log4j2، لاحقًا.
وهذا يفصل تطبيقكم عن خيارات تنفيذ التسجيل.
public class Main {
public static void main(String[] args) {
// Concept: your code calls a facade interface, not a concrete logger
System.out.println("App -> SLF4J facade -> Logback backend");
}
}لماذا لا نستخدم مجرد راية منطقية؟
تستخدم بعض الشيفرات if (DEBUG) System.out.println(...). وهذا ينشر الشروط في أنحاء قاعدة الشيفرة ولا يوفر تحكمًا مستقلًا لكل حزمة.
يوحّد إطار التسجيل الإعدادات في مكان واحد: فعّلوا DEBUG لحزمة واحدة، وERROR لكل ما عداها.
public class Main {
static final boolean DEBUG = false;
public static void main(String[] args) {
// Inflexible: one global switch, scattered checks
if (DEBUG) System.out.println("diagnostic");
System.out.println("A framework controls this per logger instead");
}
}اعتبارات الأداء
ينبغي أن تكون تكلفة التسجيل منخفضة عند تعطيله. فتتخطى الأطر العمل الخاصة بالمستويات المصفّاة، كما تتجنب الرسائل ذات المعلمات إنشاء سلاسل نصية ستتخلصون منها.
أما println فيقيّم وسيطه دائمًا، حتى إن لم يقرأ أحد المخرجات.
public class Main {
static String expensive() {
System.out.println("(building expensive string)");
return "big report";
}
public static void main(String[] args) {
boolean debugEnabled = false;
// Only build the message if it will actually be logged
if (debugEnabled) System.out.println(expensive());
System.out.println("skipped expensive work");
}
}توجيه المخرجات مركزيًا
ترسل الأطر السجلات إلى appenders واحد أو أكثر: وحدة التحكم أو الملفات المتداولة أو syslog أو جامع شبكي.
تضبطون التوجيه مرة واحدة، وتبقى شيفرة التطبيق كما هي.
public class Main {
public static void main(String[] args) {
String[] appenders = {"CONSOLE", "ROLLING_FILE", "JSON_HTTP"};
for (String a : appenders) System.out.println("route logs to: " + a);
}
}الربط والسياق
تضيف الأنظمة الحقيقية معرّف طلب إلى كل سطر سجل ضمن الطلب، حتى تتمكنوا من تتبع رحلة مستخدم واحد عبر سلاسل التنفيذ والخدمات.
يدعم SLF4J ذلك من خلال MDC (Mapped Diagnostic Context).
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, String> mdc = new HashMap<>();
mdc.put("requestId", "req-1234");
System.out.println("All logs in this request tagged with " + mdc);
}
}الخطة
خلال هذه الدورة ستتعلّمون ما يلي:
- استخدام واجهة SLF4J الوسيطة والحصول على المسجّلات.
- التسجيل عند المستوى المناسب.
- استخدام الرسائل ذات المعلمات لتحقيق الكفاءة.
- إعداد Logback باستخدام appenders والأنماط.
public class Main {
public static void main(String[] args) {
System.out.println("Next: SLF4J facade and loggers");
}
}اختبار سريع
اختبروا مدى فهمكم للتسجيل المنظم.
مراجعة
لقد تعلمتم سبب أهمية التسجيل المنظم:
- تفتقر println إلى المستويات والبيانات الوصفية والتوجيه.
- تضيف أُطر العمل المستويات والتصفية والمُلحقات.
- تفصل الواجهة التجريدية الكود عن الواجهة الخلفية.
- يتيح السياق المنظم وMDC إجراء الربط بين الأحداث.
في الدرس التالي، سنتناول واجهة SLF4J التجريدية وإنشاء المسجّلات.
public class Main {
public static void main(String[] args) {
System.out.println("Structured logging recap complete");
}
}الأسئلة الشائعة
هل درس «لماذا التسجيل المنظّم» مجاني؟
نعم — نص درس «لماذا التسجيل المنظّم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.
ماذا ستتعلم في «لماذا التسجيل المنظّم»؟
ما بعد System.out.println تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟
لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «لماذا التسجيل المنظّم»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟
نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- لماذا التسجيل المنظّم
- واجهة SLF4J والمسجلات
- التسجيل المعلَّم بالمعلمات
- تهيئة Logback