أهلاً! عند كتابة الدروس، أؤكد بشكل خاص على ما إذا كان هناك موضوع محدد سيكون ضروريًا للغاية في العمل الحقيقي. لذا، استمع! من المؤكد أن الموضوع الذي سنغطيه اليوم سيكون مفيدًا في جميع مشاريعك منذ اليوم الأول للتوظيف. سنتحدث عن تسجيل جافا. هذا الموضوع ليس معقدًا على الإطلاق (أود أن أقول أنه سهل). ولكن سيكون لديك ما يكفي من الأشياء الواضحة للتركيز عليها في وظيفتك الأولى، لذا من الأفضل أن تفهمها جيدًا الآن :) حسنًا، فلنبدأ.
ما هو تسجيل الدخول في جافا؟
التسجيل هو عملية تسجيل البيانات حول تشغيل البرنامج. المكان الذي نسجل فيه هذه البيانات يسمى "السجل". هناك سؤالان على الفور: ما هي البيانات المكتوبة وأين؟ لنبدأ بـ "أين". يمكنك كتابة بيانات حول عمل البرنامج في العديد من الأماكن المختلفة. على سبيل المثال، أثناء دراستك، غالبًا ما تقوم System.out.println()لإخراج البيانات إلى وحدة التحكم. وهذا بالفعل تسجيل، وإن كان في أبسط أشكاله. بالطبع، هذا ليس مناسبًا جدًا للمستخدمين أو فريق دعم المنتج: من الواضح أنهم لن يرغبوا في تثبيت IDE ومراقبة وحدة التحكم :) هناك تنسيق أكثر اعتيادية لتسجيل المعلومات: الملفات النصية. يشعر البشر براحة أكبر في قراءة البيانات بهذا التنسيق، ومن المؤكد أنه أكثر ملاءمة لتخزين البيانات! الآن السؤال الثاني: ما هي بيانات البرنامج التي يجب تسجيلها؟ هذا متروك لك تماما! نظام التسجيل في Java مرن للغاية. يمكنك تكوينه لتسجيل كل ما يفعله برنامجك. من ناحية، هذا أمر جيد. لكن من ناحية أخرى، تخيل حجم سجلات فيسبوك أو تويتر إذا كتبوا كل شيء فيها. ربما تمتلك هذه الشركات الكبيرة القدرة على تخزين هذا القدر من البيانات. لكن تخيل مدى صعوبة العثور على معلومات حول خطأ فادح واحد في 500 غيغابايت من السجلات النصية؟ سيكون ذلك أسوأ من البحث عن إبرة في كومة قش. وبناءً على ذلك، يمكن تكوين Java لتسجيل بيانات الخطأ فقط. أو حتى مجرد أخطاء فادحة! ومع ذلك، ليس من الدقة تمامًا الحديث عن نظام التسجيل الأصلي لجافا. والحقيقة هي أن المبرمجين كانوا بحاجة إلى التسجيل قبل إضافة هذه الوظيفة إلى اللغة. بحلول الوقت الذي قدمت فيه Java مكتبة التسجيل الخاصة بها، كان الجميع يستخدمون مكتبة log4j بالفعل. إن تاريخ تسجيل الدخول إلى Java طويل جدًا وغني بالمعلومات. باختصار، لدى Java مكتبة تسجيل خاصة بها، لكن لا أحد يستخدمها تقريبًا :) في وقت لاحق، عندما ظهرت العديد من مكتبات التسجيل المختلفة وبدأ المبرمجون في استخدامها، نشأت مشاكل التوافق. لمنع الأشخاص من إعادة اختراع العجلة في عشرات المكتبات المختلفة بواجهات مختلفة، تم إنشاء إطار عمل SLF4J المجرد ("واجهة تسجيل الخدمة لـ Java"). يطلق عليه اسم مجردة، لأنه حتى إذا كنت تستخدم أساليب فئات SLF4J وتستدعيها، فإنها تستخدم في الواقع جميع أطر عمل التسجيل التي جاءت من قبل: log4j، وjava.util.logging القياسي، وغيرها. إذا كنت في مرحلة ما تحتاج إلى بعض الميزات المحددة في Log4j التي تفتقر إليها المكتبات الأخرى، ولكنك لا تريد ربط مشروعك مباشرة بهذه المكتبة، فما عليك سوى استخدام SLF4J. ثم دعها تستدعي أساليب Log4j. إذا غيرت رأيك وقررت أنك لم تعد بحاجة إلى ميزات Log4j، فأنت تحتاج فقط إلى إعادة تكوين "المجمع" (أي SLF4J) لاستخدام مكتبة أخرى. لن يتوقف الكود الخاص بك عن العمل، لأنك تتصل بأساليب SLF4J، وليس مكتبة معينة. انحراف صغير. لكي تعمل الأمثلة التالية، تحتاج إلى تنزيل مكتبة SLF4J هنا ، ومكتبة Log4j هنا . بعد ذلك، قم بفك ضغط الأرشيف واستخدم IntelliJ IDEA لإضافة ملفات JAR إلى مسار الفصل. عناصر القائمة: ملف -> هيكل المشروع -> المكتبات حدد ملفات JAR الضرورية وأضفها إلى المشروع (تحتوي الأرشيفات التي قمنا بتنزيلها على العديد من ملفات JAR - انظر إلى الصور لرؤية الملفات التي تحتاجها) لاحظ أن هذه التعليمات لهؤلاء الطلاب الذين لا يعرفون كيفية استخدام Maven. إذا كنت تعرف كيفية استخدام Maven، فمن الأفضل عادةً (الأسهل بكثير) أن تحاول البدء من هناك. إذا كنت تستخدم Maven ، أضف هذه التبعية:<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.14.0</version>
</dependency>
عظيم! لقد اكتشفنا الإعدادات :) دعونا نرى كيف يعمل SLF4J. كيف نتأكد من أن عمل البرنامج مسجل في مكان ما؟ للقيام بذلك، نحتاج إلى شيئين: المُسجل والمُلحق. لنبدأ بالأول. المسجل هو كائن يوفر التحكم الكامل في التسجيل. يعد إنشاء المسجل أمرًا سهلاً للغاية: نقوم بذلك باستخدام أساليب LoggerFactory.getLogger() الثابتة . معلمة الطريقة هي الفئة التي سيتم تسجيل عملها. لنقم بتشغيل الكود الخاص بنا:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyTestClass {
public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);
public static void main(String[] args) {
LOGGER.info("Test log entry!!!");
LOGGER.error("An error occurred!");
}
}
إخراج وحدة التحكم:
ERROR StatusLogger No Log4j 2 configuration file found. Using default configuration (logging only errors to the console), or user programmatically provided configurations. Set system property 'log4j2.debug' to show Log4j 2 internal initialization logging. See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2 15:49:08.907 [main] ERROR MyTestClass - An error occurred!
ما الذي نراه هنا؟ أولا، نرى رسالة خطأ. هذا نتيجة لحقيقة أننا الآن نفتقر إلى الإعدادات اللازمة. وبناء على ذلك، فإن المسجل الخاص بنا قادر حاليًا فقط على إخراج رسائل الخطأ (خطأ) وإلى وحدة التحكم فقط. لم تنجح طريقة logger.info () . لكن logger.error() فعلت ذلك! في وحدة التحكم، نرى التاريخ الحالي، والطريقة التي حدث بها الخطأ ( الرئيسي )، وكلمة "خطأ"، ورسالتنا! الخطأ هو مستوى التسجيل. بشكل عام، إذا تم وضع علامة على إدخال السجل بكلمة "خطأ"، فهذا يعني أن خطأ قد حدث في هذه المرحلة في البرنامج. إذا تم وضع علامة على الإدخال بكلمة "INFO"، فإن الرسالة تمثل ببساطة المعلومات الحالية حول التشغيل العادي للبرنامج. تحتوي مكتبة SLF4J على الكثير من مستويات التسجيل المختلفة التي تتيح لك تكوين التسجيل بمرونة. كل هذا سهل الإدارة: كل المنطق الضروري موجود بالفعل في فئة Java Logger . تحتاج فقط إلى الاتصال بالطرق ذات الصلة. إذا كنت تريد تسجيل رسالة روتينية، فاتصل بالطريقة logger.info() . للحصول على رسالة خطأ، استخدم logger.error() . للحصول على تحذير، استخدم logger.warn()
الآن دعونا نتحدث عن المُلحق
الملحق هو المكان الذي تذهب إليه بياناتك. بطريقة ما، عكس مصدر البيانات، أي "النقطة ب". بشكل افتراضي، يتم إخراج البيانات إلى وحدة التحكم. لاحظ أنه في المثال السابق لم يكن علينا تكوين أي شيء: ظهر النص في وحدة التحكم، ويمكن لمسجل مكتبة Log4j فقط إخراج رسائل على مستوى الخطأ إلى وحدة التحكم. من الواضح أنه من الملائم أكثر للأشخاص قراءة السجلات وكتابتها في ملف نصي. لتغيير السلوك الافتراضي للمسجل، نحتاج إلى تكوين مُلحق الملف الخاص بنا. للبدء، تحتاج إلى إنشاء ملف log4j.xml مباشرة في المجلد src. أنت بالفعل على دراية بتنسيق XML: لقد حصلنا مؤخرًا على درس حول هذا الموضوع :) إليك محتويات الملف:<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<File name="MyFileAppender" fileName="C:\Users\Username\Desktop\testlog.txt" immediateFlush="false" append="false">
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="MyFileAppender"/>
</Root>
</Loggers>
</Configuration>
لا يوجد شيء خاص أو صعب هنا :) ولكن مع ذلك، دعنا نستعرض المحتوى.
<Configuration status="INFO">
هذا هو ما يسمى بـ StatusLogger. إنه لا علاقة له بالمسجل الخاص بنا ويستخدم في العمليات الداخلية لـ Log4j. إذا قمت بتعيين الحالة = "TRACE" بدلاً من الحالة = "INFO"، فسيتم عرض جميع المعلومات حول العمل الداخلي لـ Log4j على وحدة التحكم (يعرض StatusLogger البيانات على وحدة التحكم، حتى لو كان المُلحق ملفًا). نحن لسنا بحاجة إليها الآن، لذلك دعونا نترك الأمر كما هو.
<Appenders>
<File name="MyFileAppender" fileName="C:\Users\Evgeny\Desktop\testlog.txt" append="true">
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
هنا نقوم بإنشاء المُلحق الخاص بنا. تشير العلامة <File> إلى أنه سيكون مُلحق ملف. name="MyFileAppender" يعين اسم المُلحق. يشير fileName = "C:\Users\Username\Desktop\testlog.txt" إلى المسار إلى ملف السجل حيث سيتم كتابة كافة البيانات. يشير الملحق = "true" إلى ما إذا كان يجب كتابة البيانات في نهاية الملف. وفي حالتنا، هذا هو بالضبط ما سنفعله. إذا قمت بتعيين القيمة على خطأ، فسيتم حذف المحتويات القديمة لملف السجل في كل مرة يتم فيها تشغيل البرنامج. <PatternLayout Pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> يشير إلى إعدادات التنسيق . يمكننا هنا استخدام التعبيرات العادية لتخصيص كيفية تنسيق النص في سجلنا.
<Loggers>
<Root level="INFO">
<AppenderRef ref="MyFileAppender"/>
</Root>
</Loggers>
هنا نشير إلى مستوى الجذر. لقد قمنا بتعيين مستوى "INFO"، مما يعني أن جميع الرسائل التي مستوياتها أعلى من INFO (حسب الجدول الذي استعرضناه أعلاه) لن يتم تسجيلها. سيحتوي برنامجنا على 3 رسائل: واحدة معلومات، وواحدة تحذير، وواحدة خطأ. مع التكوين الحالي، سيتم تسجيل كافة الرسائل الثلاث. إذا قمت بتغيير مستوى الجذر إلى خطأ، فستنتهي الرسالة الأخيرة فقط من استدعاء الأسلوب LOGGER.error() في السجل. بالإضافة إلى ذلك، توجد إشارة إلى المُلحق هنا أيضًا. لإنشاء مثل هذا المرجع، تحتاج إلى إنشاء علامة <ApprenderRef> داخل علامة <Root> وإضافة السمة ref='your appender's name' إليها. في حالة نسيانك، فهذا هو المكان الذي قمنا فيه بتعيين اسم المُلحق: <File name="MyFileAppender" . وهنا الكود الخاص بنا!
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyTestClass {
public static final Logger LOGGER = LoggerFactory.getLogger(MyTestClass.class);
public static void main(String[] args) {
LOGGER.info("The program is starting!!!");
try {
LOGGER.warn("Attention! The program is trying to divide a number by another.
System.out.println(12/0);
} catch (ArithmeticException x) {
LOGGER.error("Error! Division by zero!");
}
}
}
بالطبع، هذا أمر غريب بعض الشيء (التقاط RuntimeException فكرة مشكوك فيها)، لكنه مثالي لأغراضنا :) فلنقم بتشغيل طريقتنا main() 4 مرات متتالية وإلقاء نظرة على ملف testlog.txt الخاص بنا. لا تحتاج إلى إنشائه مسبقًا: ستقوم المكتبة بذلك تلقائيًا. كل شيء يعمل! :) الآن لديك مسجل تكوينه. يمكنك تجربة بعض برامجك القديمة، وإضافة مكالمات مسجلة لكل طريقة. ثم انظر إلى السجل الناتج :) فهو يتناول موضوع التسجيل بعمق. سيكون من الصعب قراءتها كلها في جلسة واحدة. ومع ذلك، فهو يحتوي على الكثير من المعلومات الإضافية المفيدة. على سبيل المثال، ستتعلم كيفية تكوين المسجل بحيث يقوم بإنشاء ملف نصي جديد إذا وصل ملف testlog.txt الخاص بنا إلى حجم معين :) وبهذا نختتم فصلنا! لقد تعرفت اليوم على موضوع مهم للغاية، ومن المؤكد أن هذه المعرفة ستكون مفيدة لك في عملك المستقبلي. حتى المرة القادمة! :)
GO TO FULL VERSION