مرحبًا بالجميع في مجتمع CodeGym!
اليوم دعونا نتحدث عن التسجيل:
- ما هو، ولماذا يوجد، ومتى يجب عليك استخدامه، ومتى يجب عليك تجنبه.
- ما هي تطبيقات التسجيل المتوفرة في Java، وما يجب عليك فعله بكل خيارات التسجيل هذه.
ومستويات السجل. سنناقش ماهية المُلحق وكيفية تكوينه بشكل صحيح.
- عقد التسجيل وكيفية تكوينها بشكل صحيح بحيث يعمل كل شيء بالطريقة التي نريدها.
هذه المادة مخصصة لجمهور واسع. سيكون الأمر واضحًا لأي شخص يعرف Java للتو، بالإضافة إلى الأشخاص الذين يعملون بالفعل ولكنهم لم يستكشفوا سوى
logger.info("log something");
Let's go!
لماذا تحتاج التسجيل؟
دعونا نلقي نظرة على بعض الحالات الحقيقية حيث يمكن أن يحل التسجيل مشكلة ما. هنا مثال من عملي. هناك نقاط يتكامل فيها التطبيق مع الخدمات الأخرى. أستخدم التسجيل في هذه النقاط لإنشاء نوع من
"العذر" : إذا لم ينجح التكامل، يصبح من السهل معرفة الجانب الذي لديه المشكلة. ومن المستحسن أيضًا تسجيل المعلومات المهمة المخزنة في قاعدة البيانات. على سبيل المثال، إنشاء مستخدم المسؤول. هذا هو بالضبط نوع الشيء الذي سيكون من الجيد تسجيله.
أدوات لتسجيل الدخول إلى جافا
ومن بين حلول التسجيل المعروفة في جافا يمكننا تسليط الضوء على ما يلي:
- Log4j
- يوليو - java.util.logging
- JCL - تسجيل جاكرتا كومنز
- تسجيل الدخول مرة أخرى
- SLF4J — واجهة تسجيل بسيطة لجافا
وسنقدم لمحة عامة عن كل واحد منهم. ثم سنأخذ ربط slf4j - log4j كأساس للمناقشة العملية. قد يبدو هذا غريبًا الآن، لكن لا تقلق: بحلول نهاية المقال، سيكون كل شيء واضحًا. |
System.err.println
في البداية، كان هناك
System.err.println (عرض إدخالات السجل على وحدة التحكم). حتى اليوم، يتم استخدام هذه التقنية للتسجيل بسرعة عند تصحيح الأخطاء. بالطبع، لا توجد إعدادات للمناقشة هنا، لذا فقط تذكر هذه الطريقة وسنمضي قدمًا.
Log4j
هذا هو الحل الكامل الذي ابتكره المطورون بدافع الضرورة. والنتيجة هي أداة مثيرة للاهتمام حقًا يمكنك استخدامها. نظرًا لظروف مختلفة، لم يصل هذا الحل إلى JDK، وهي حقيقة أزعجت المجتمع بأكمله بشكل كبير. يحتوي Log4j على خيارات تكوين تتيح لك تمكين تسجيل الدخول إلى
com.example.type
الحزمة وإيقاف تشغيلها في
com.example.type.generic
الحزمة الفرعية. وهذا يجعل من الممكن استبعاد التعليمات البرمجية التي لا تحتاج إلى تسجيلها بسرعة. ومن المهم أن نلاحظ هنا أن
هناك إصدارين من Log4j: 1.2.x و2.xx، وهما غير متوافقين مع بعضهما البعض . أضاف Log4j مفاهيم
الملحق (أداة تستخدم لكتابة السجلات) والتخطيط (تنسيق السجل). يتيح لك هذا تسجيل ما تحتاجه فقط وتسجيله بالطريقة التي تريدها. سنتحدث أكثر عن المُلحق بعد قليل.
يوليو - java.util.logging
إحدى الفوائد الرئيسية لهذا الحل هو تضمين JUL في JDK (Java Development Kit). لسوء الحظ، عندما تم تطويره، لم يعتمد منشئوه على الأداة المساعدة Log4j الشهيرة، بل على حل من IBM. وكان لهذا القرار عواقب. الحقيقة هي أنه لا أحد يستخدم JUL الآن. تختلف مستويات السجل في JUL عما يحتويه Logback وLog4j وSlf4j. وهذا يجعل من الصعب عليهم فهم بعضهم البعض. إنشاء المسجل يشبه إلى حد ما. للقيام بذلك، عليك القيام بالاستيراد:
java.util.logging.Logger log = java.util.logging.Logger.getLogger(LoggingJul.class.getName());
تم تمرير اسم الفئة، حتى نعرف من أين سيأتي تسجيلنا. بدءًا من Java 8، يمكنك تمرير ملفات
Supplier<String>
. وهذا يساعدنا على قراءة وإنشاء سطر فقط عندما نحتاج إليه حقًا، وليس في كل مرة، كما كان الحال سابقًا. فقط مع إصدار Java 8 تمكن المطورون أخيرًا من حل المشكلات المهمة وجعلوا JUL قابلاً للاستخدام حقًا. وهي الطرق ذات
Supplier<String> msgSupplier
المعلمة، كما هو موضح أدناه:
public void info(Supplier<String> msgSupplier) {
log(Level.INFO, msgSupplier);
}
JCL - تسجيل جاكرتا كومنز
نظرًا لعدم وجود معيار صناعي فيما يتعلق بالتسجيل لفترة طويلة وقام العديد من الأشخاص بإنشاء أدوات قطع الأشجار المخصصة الخاصة بهم، فقد تم اتخاذ القرار لإصدار JCL، وهو غلاف عام يمكن استخدامه فوق الآخرين. لماذا؟ في بعض الأحيان تستخدم التبعيات المضافة إلى المشروع مسجلاً مختلفًا عن المسجل الموجود في المشروع. ولهذا السبب، تمت إضافتها إلى المشروع كتبعيات متعدية، وهذا خلق مشاكل حقيقية عند محاولة تجميع كل شيء معًا. لسوء الحظ، لم يكن المجمع فعالاً للغاية ولم يضيف أي شيء. ربما يكون الأمر مناسبًا إذا استخدم الجميع JCL. ولكن هذا ليس ما حدث، لذا فإن استخدام JCL ليس هو أفضل فكرة في الوقت الحالي.
تسجيل الدخول مرة أخرى
المسار مفتوح المصدر شائك ... نفس المطور الذي كتب Log4j كتب أيضًا Logback كإطار عمل لاحق للتسجيل. كان يعتمد على نفس فكرة Log4j. الاختلافات في Logback هي:
- تحسين الأداء
- تمت إضافة دعم أصلي لـ Slf4j
- خيارات التصفية الموسعة
افتراضيًا، لا يتطلب Logback أي تكوين، ويسجل كافة الأحداث على مستوى DEBUG وما فوق. إذا كنت بحاجة إلى بعض التخصيص، فيمكنك تحقيق ذلك من خلال تكوين XML:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<encoder>
<pattern>%d{HH:mm:ss,SSS} %-5p [%c] - %m%n</pattern>
</encoder>
</appender>
<logger name="org.hibernate.SQL" level="DEBUG" />
<logger name="org.hibernate.type.descriptor.sql" level="TRACE" />
<root level="info">
<appender-ref ref="FILE" />
</root>
</configuration>
SLF4J — واجهة تسجيل بسيطة لجافا
في وقت ما من عام 2006، ترك أحد الآباء المؤسسين لـ Log4j المشروع وأنشأ Slf4j (واجهة تسجيل بسيطة لـ Java)، وهو عبارة عن غلاف لـ Log4j وJUL والتسجيل المشترك وLogback. كما ترون، لقد تقدمنا إلى حد إنشاء غلاف فوق غلاف... في هذه الحالة، يتم تقسيمه إلى جزأين: واجهة برمجة التطبيقات (API) المستخدمة في التطبيق، والتنفيذ الذي تتم إضافته بعناصر منفصلة التبعيات لكل نوع من التسجيل. على سبيل المثال،
slf4j-log4j12.jar
و
slf4j-jdk14.jar
. أنت بحاجة إلى ربط التنفيذ الصحيح وهذا كل شيء: سيستخدمه مشروعك بأكمله. يدعم Slf4j كافة الميزات الأحدث، مثل تنسيق السلاسل للتسجيل. في السابق، كانت هناك مثل هذه المشكلة. لنفترض أننا قمنا بإنشاء إدخال سجل مثل هذا:
log.debug("User " + user + " connected from " + request.getRemoteAddr());
بسبب عامل التسلسل،
user
يصبح الكائن سلسلة بصمت بفضل
user.toString()
. وهذا يستغرق وقتا ويبطئ النظام. وقد يكون ذلك جيدًا إذا كنا نقوم بتصحيح أخطاء التطبيق. نبدأ في مواجهة المشكلات إذا كان مستوى السجل لهذه الفئة هو INFO أو أعلى. بمعنى آخر، لا ينبغي لنا أن نكتب إدخال السجل هذا (للمعلومات أو أعلى)، ولا ينبغي لنا أن نستخدم تسلسل السلسلة. من الناحية النظرية، يجب على مكتبة التسجيل نفسها معالجة هذا الأمر. وفي الواقع، تبين أن هذه هي المشكلة الأكبر في الإصدار الأول من Log4j. لم يقدم حلاً مناسبًا، ولكنه اقترح بدلاً من ذلك القيام بشيء مثل هذا:
if (log.isDebugEnabled()) {
log.debug("User " + user + " connected from " + request.getRemoteAddr());
}
وهذا يعني أنه بدلاً من سطر واحد من التعليمات البرمجية للتسجيل، اقترحوا كتابة 3! يجب أن يقلل التسجيل من تغييرات التعليمات البرمجية، ومن الواضح أن الأسطر الثلاثة تنتهك هذا النهج العام. لم يواجه Slf4j أية مشكلات في التوافق مع JDK وAPI، لذلك ظهر حل جيد على الفور:
log.debug("User {} connected from {}", user, request.getRemoteAddr());
حيث
{}
تشير إلى العناصر النائبة للوسائط التي تم تمريرها إلى الطريقة. أي أن الأول
{}
يقابله
user
والثاني
{}
يقابله
request.getRemoteAddr()
. من خلال القيام بذلك بهذه الطريقة، سنقوم بإجراء تسلسل السلسلة فقط إذا كان مستوى السجل يتطلب منا كتابة إدخال السجل. بعد ذلك، بدأت شعبية Sjf4j تنمو بسرعة. في الوقت الحاضر، هو الحل الأفضل. وبناء على ذلك، دعونا نلقي نظرة على التسجيل باستخدام
slf4j-log4j12
الربط.
ما يجب تسجيله
وبطبيعة الحال، لا ينبغي عليك تسجيل كل شيء. وهذا ليس ضروريًا في كثير من الأحيان، بل وخطير في بعض الأحيان. على سبيل المثال، إذا قمت بتسجيل بيانات شخصية لشخص ما وتم تسريبها بطريقة أو بأخرى، فستكون هناك مشاكل حقيقية، خاصة في المشاريع التي تركز على الأسواق الغربية. ولكن هناك أيضًا
أشياء يجب عليك تسجيلها بالتأكيد :
- بداية/نهاية التطبيق. نحتاج إلى معرفة ما إذا كان التطبيق قد بدأ بالفعل وانتهى كما هو متوقع.
- القضايا الأمنية. سيكون من الجيد هنا تسجيل محاولات تخمين كلمة مرور شخص ما، والحالات التي يقوم فيها المسؤولون بتسجيل الدخول، وما إلى ذلك.
- حالات تطبيق معينة . على سبيل المثال، الانتقال من حالة إلى أخرى في عملية تجارية.
- معلومات تصحيح معينة بالإضافة إلى مستوى السجل المقابل.
- بعض البرامج النصية SQL. هناك حالات في العالم الحقيقي عندما يكون ذلك ضروريا. ولكن مرة أخرى، من خلال ضبط مستويات السجل بمهارة، يمكنك تحقيق نتائج ممتازة.
- يمكن تسجيل سلاسل العمليات الجارية عند التحقق من أن الأمور تعمل بشكل صحيح.
الأخطاء الشائعة في التسجيل
هناك العديد من الفروق الدقيقة هنا، لكننا سنذكر بشكل خاص بعض الأخطاء الشائعة:
- قطع الأشجار المفرط. لا يجب عليك تسجيل كل خطوة قد تكون مهمة من الناحية النظرية. هنا قاعدة جيدة: يجب ألا تتجاوز السجلات 10% من الحمل. وإلا ستكون هناك مشاكل في الأداء.
- تسجيل جميع البيانات في ملف واحد. في مرحلة ما، سيجعل هذا من الصعب جدًا قراءة/كتابة السجل، ناهيك عن حقيقة أن بعض الأنظمة لها حدود على حجم الملف.
- استخدام مستويات سجل غير صحيحة. لكل مستوى سجل حدود واضحة، ويجب احترامها. إذا كانت الحدود غير واضحة، يمكنك التوصل إلى اتفاق حول المستوى الذي سيتم استخدامه.
مستويات السجل
|
|
|
س: مرئية |
|
|
|
|
مميت |
خطأ |
تحذير |
معلومات |
تصحيح |
يتعقب |
الجميع |
عن |
|
|
|
|
|
|
|
مميت |
س |
|
|
|
|
|
|
خطأ |
س |
س |
|
|
|
|
|
تحذير |
س |
س |
س |
|
|
|
|
معلومات |
س |
س |
س |
س |
|
|
|
تصحيح |
س |
س |
س |
س |
س |
|
|
يتعقب |
س |
س |
س |
س |
س |
س |
|
الجميع |
س |
س |
س |
س |
س |
س |
س |
ما هي مستويات السجل؟ من أجل إنشاء تسلسل هرمي لإدخالات السجل بطريقة أو بأخرى، هناك حاجة إلى بعض الاتفاقيات والحدود. ولهذا السبب تم تقديم مستويات السجل. يتم تحديد المستوى في التطبيق. إذا كان الإدخال أقل من مستوى محدد، فلن يتم تسجيله. على سبيل المثال، لدينا سجلات نستخدمها عند تصحيح أخطاء التطبيق. أثناء التشغيل العادي (عند استخدام التطبيق للغرض المقصود منه)، لا تكون هناك حاجة لمثل هذه السجلات. ولذلك، يكون مستوى السجل أعلى من مستوى التصحيح. دعونا نلقي نظرة على مستويات السجل باستخدام Log4j. وبصرف النظر عن JUL، تستخدم الحلول الأخرى نفس مستويات السجل. وهنا هم في ترتيب تنازلي:
- OFF: لا يتم تسجيل أي إدخالات سجل؛ يتم تجاهل كل شيء.
- فادح: خطأ يمنع التطبيق من الاستمرار في التشغيل. على سبيل المثال، "خطأ في ذاكرة JVM".
- خطأ: تشير الأخطاء عند هذا المستوى إلى مشاكل تحتاج إلى حل. الخطأ لا يوقف التطبيق ككل. قد تعمل الطلبات الأخرى بشكل صحيح.
- تحذير: إدخالات السجل التي تمثل تحذيرًا. حدث شيء غير متوقع، لكن النظام تمكن من التأقلم والوفاء بالطلب
- معلومات: إدخالات السجل التي تشير إلى الإجراءات المهمة في التطبيق. هذه ليست أخطاء أو تحذيرات. وهي أحداث النظام المتوقعة.
- التصحيح: تحتاج إدخالات السجلات إلى تصحيح أخطاء التطبيق. للتأكد من أن التطبيق يفعل بالضبط ما هو متوقع، أو لوصف الإجراءات التي اتخذها التطبيق، أي "تم إدخال الطريقة 1".
- TRACE: إدخالات سجل ذات أولوية منخفضة لتصحيح الأخطاء. أدنى مستوى سجل.
- ALL: مستوى السجل لكتابة كافة إدخالات سجل التطبيق.
في مستوى سجل INFO يتم تمكينه في مكان ما في التطبيق، ثم سيتم تسجيل الإدخالات لكل مستوى، من INFO إلى FATAL. إذا تم تعيين مستوى السجل FATAL، فسيتم كتابة إدخالات السجل فقط بهذا المستوى.
تسجيل وإرسال السجلات: Appender
دعونا نفكر في كيفية عمل كل هذا عندما نستخدم Log4j، والذي يوفر فرصًا كبيرة لكتابة/إرسال السجلات:
- للكتابة إلى ملف -
DailyRollingFileAppender
- لكتابة المعلومات إلى وحدة التحكم -
ConsoleAppender
- لكتابة السجلات إلى قاعدة البيانات -
JDBCAppender
- لإدارة إرسال السجلات عبر TCP/IP —
TelnetAppender
- لضمان أن التسجيل لا يؤثر سلبًا على الأداء -
AsyncAppender
هناك عدد قليل من التطبيقات الأخرى: القائمة الكاملة متاحة
هنا
. بالمناسبة، إذا كان المُلحق الذي تحتاجه غير موجود، فلا توجد مشكلة. يمكنك كتابة المُلحق الخاص بك عن طريق تنفيذ واجهة
المُلحق التي يدعمها Log4j.
عقد التسجيل
لأغراض العرض التوضيحي، سوف نستخدم واجهة Slf4j، مع تطبيق من Log4j. يعد إنشاء المسجل أمرًا بسيطًا للغاية: في فئة تسمى
MainDemo
، والتي ستقوم ببعض عمليات التسجيل، نحتاج إلى إضافة ما يلي:
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(MainDemo.class);
سيؤدي هذا إلى إنشاء مسجل لنا. لإجراء إدخال سجل، هناك العديد من الطرق المتاحة التي تعكس أسماؤها مستوى السجل الذي سيتم استخدامه. على سبيل المثال:
logger.trace("Method 1 started with argument={}", argument);
logger.debug("Database updated with script = {}", script);
logger.info("Application has started on port = {}", port);
logger.warn("Log4j didn't find the log4j.properties file. Please fix this.");
logger.error("Connection refused to host = {}", host);
على الرغم من أننا نجتاز الفصل، إلا أن الاسم النهائي هو الاسم الكامل للفئة، بما في ذلك الحزم. يتم ذلك بحيث يمكنك لاحقًا تقسيم التسجيل إلى عقد وتكوين مستوى التسجيل والملحق لكل عقدة. على سبيل المثال، تم إنشاء المسجل في
com.github.romankh3.logginglecture.MainDemo
الفصل الدراسي. يوفر الاسم الأساس لإنشاء تسلسل هرمي لعقد التسجيل. العقدة الرئيسية هي
RootLogger ذات المستوى الأعلى . هذه هي العقدة التي تتلقى كافة إدخالات السجل للتطبيق بأكمله. يمكن تصوير العقد المتبقية كما هو موضح أدناه:
يتم تكوين المُلحقين لعقد تسجيل محددة. سنلقي الآن نظرة على ملف
log4j.properties لنرى مثالاً لكيفية تكوينها.
دليل خطوة بخطوة لملف log4j.properties
سنقوم بإعداد كل شيء خطوة بخطوة ونرى ما هو ممكن:
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
يشير هذا السطر إلى أننا نقوم بتسجيل مُلحق CONSOLE، الذي يستخدم تطبيق org.apache.log4j.ConsoleAppender. يقوم هذا المُلحق بكتابة المعلومات إلى وحدة التحكم. بعد ذلك، نقوم بتسجيل مُلحق آخر. هذا واحد سوف يكتب إلى ملف:
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
من المهم ملاحظة أن المُلحقين أنفسهم ما زالوا بحاجة إلى التهيئة. بمجرد تسجيل المُلحقين لدينا، يمكننا تحديد مستويات السجل والملحقين الذين سيتم استخدامهم في العقد.
log4j.rootLogger=تصحيح الأخطاء، وحدة التحكم، ملف
- يعني log4j.rootLogger أننا نقوم بتكوين العقدة الجذرية، التي تحتوي على كافة إدخالات السجل
- تشير الكلمة الأولى بعد علامة التساوي إلى الحد الأدنى لمستوى السجل المراد كتابته (في حالتنا، هو DEBUG)
- بعد الفاصلة، نشير إلى جميع المُلحقات التي سيتم استخدامها.
لتكوين عقدة تسجيل أكثر تحديدًا، يمكنك استخدام إدخال مثل هذا:
log4j.logger.com.github.romankh3.logginglecture=TRACE, OWN, CONSOLE
حيث
log4j.logger.
يتم استخدامه للإشارة إلى عقدة معينة. في حالتنا،
com.github.romankh3.logginglecture.
لنتحدث الآن عن تكوين مُلحق CONSOLE:
# CONSOLE appender customization
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.threshold=DEBUG
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=[%-5p] : %c:%L : %m%n
نرى هنا أنه من الممكن تعيين المستوى المحدد الذي سيبدأ المُلحق العمل عنده. فيما يلي مثال لما يحدث بالفعل: لنفترض أن عقدة التسجيل استقبلت رسالة بمستوى INFO وتم تمريرها إلى المُلحق المخصص لها. إذا تم تعيين عتبة المُلحق على WARN، فإنه يتلقى إدخال السجل ولكنه لا يفعل شيئًا به. بعد ذلك، نحتاج إلى تحديد التخطيط الذي ستستخدمه الرسالة. أستخدم PatternLayout في المثال، ولكن هناك العديد من الخيارات الأخرى. لن نغطيها في هذه المقالة. مثال على تكوين المُلحق FILE:
# File appender customization
log4j.appender.FILE=org.apache.log4j.RollingFileAppender
log4j.appender.FILE.File=./target/logging/logging.log
log4j.appender.FILE.MaxFileSize=1MB
log4j.appender.FILE.threshold=DEBUG
log4j.appender.FILE.MaxBackupIndex=2
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=[ %-5p] - %c:%L - %m%n
يمكنك تكوين الملف المحدد الذي سيتم كتابة إدخالات السجل عليه، كما يتبين من هذا السطر:
log4j.appender.FILE.File=./target/logging/logging.log
يتم كتابة الإدخال إلى
logging.log
الملف. لتجنب مشاكل حجم الملف، يمكنك تكوين الحد الأقصى، وهو في هذه الحالة هو 1 ميغابايت.
MaxBackupIndex
يشير إلى عدد ملفات السجل التي ستكون موجودة. إذا أردنا إنشاء ملفات أكثر من هذا، فسيتم حذف الملف الأول. لإلقاء نظرة على مثال حقيقي حيث تم تكوين التسجيل، يمكنك الذهاب إلى
المستودع العام
على GitHub.
تعزيز ما ناقشناه
حاول بنفسك أن تفعل كل ما وصفناه:
- قم بإنشاء مشروعك الخاص على غرار مثالنا أعلاه.
- إذا كنت تعرف كيفية استخدام Maven، فاستخدمه. إذا لم يكن الأمر كذلك، فاقرأ هذا
البرنامج التعليمي الذي يصف كيفية توصيل المكتبة.
في ملخص
- تحدثنا عن حلول التسجيل الموجودة في Java.
- تقريبا كل مكتبات التسجيل المشهورة كتبها شخص واحد :D
- لقد تعلمنا ما ينبغي وما لا ينبغي تسجيله.
- لقد اكتشفنا مستويات السجل.
- لقد تعرفنا على عقد التسجيل.
- لقد نظرنا إلى ما هو الملحق وما هو الغرض منه.
- لقد أنشأنا ملف log4j.proterties خطوة بخطوة.
مواد إضافية
- CodeGym: درس المسجل
- أسبوعي غريب الأطوار: تسجيل جافا. مرحبا بالعالم
- رعب الترميز: مشكلة التسجيل
- يوتيوب: فهم جحيم تسجيل جافا - الأساسيات. جافا تسجيل الجحيم وكيفية البقاء بعيدا عنه
- Log4j: المُلحق
- Log4j: التخطيط
أنظر أيضا مقالتي الأخرى:
GO TO FULL VERSION