الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ما هو ال Logger وما فائدته

بدأه Eng.Helmy في 15 سبتمبر 2009 · 18 رد · 2,875 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكــم ورحمـة الله وبركاتــه ،،

ما هي ال

Logger ?

ومتى احتاجها

وجزاكم الله خيرا

#2

وعليكــم السـلام ورحمة الله وبركاتـه..

هل حصل أثناء متابعتك لأحد البرامج التي كتبتها أن تضع System.out.println بعد كل عملية للكي تتحقق من أحدى القيم ، وبعد التأكد تقوم بمسحها ؟؟

هل حصل أن قمت بكتابة برامج وفي الtry ... catch تضع للمستخدم رسالة نصيه تفيده بالخطأ ؟ ماذا لو اتصل عليك وقال أن هذه الرسالة تظهر دائما ؟ عليك كبمرمج أن تعرف سبب هذا الexcpetion ؟

لذلك في هذه الحالتين ستضع Logger وهي طريقة تمكنك من كتابة هذه المعلومات (سواء القيم التي تريد التحقق منها ، أو الException الناتج للمستخدم) في أحدى الأماكن سواء في الconsole أو في ملف ، هذا يعتمد على حسب الHandler التي ستضعه في الLogger .

التعامل مع الLogger في جافا باستخدام java.util.loggin.Logger ليس مباشرا ويحتاج لعمل بعض الconfiguration . سأضع مثالا الليلة على ذلك ان شاء الله ..

ولمن له تجربة مع الLogger يمكن أن يشارك معنا ، ليكون مرجعا جيد في استخدام الLogging system .

بالتوفيق ،

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

#3

شيء آخر بالنسبة للLogger، فكل رسالة log يتم كتابتها يكون لديها درجة Level خاص بها. يوجد خمس درجات

  • SEVERE (highest value)
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST (lowest value)

ما فائدة هذه الدرجات؟؟ هي تفيد في عمل غربلة filtre للرسائل. فمثلا يمكنك أن تطلب من البرنامج أن يكتب الرسائل من درجة SEVERE فقط، يعني الرسائل ذات الأهمية الكبرى، أو أي درجة أخرى، هذا يعتمد على حاجتك

للحصول على Logger نستخدم السطر التالي

Logger logger = Logger.getLogger("testlogger");

هنا قمنا بإنشاء Logger عن طريق الgetLogger، الString الذي نمرره للميثود هو إسم الLogger، كل Logger ننشئه يجب إعطاءه إسم خاص به

كل Logger يحتاج إلى Handler، هذا الأخير هو الذي يقوم فعليا بكتابة الرسائل، وLogger يكتفي فقط بتمريرها له. يوجد عدة أنواع من الHandler، لكننا سنستعمل FileHandler لأننا نريد كتابة الرسائل في ملف


logger.addHandler(handler);
FileHandler handler = new FileHandler("testlog.log");

كل الرسائل سيتم كتابتها في الملف testlog.log. كل Handler لديه Formatter خاص به، هذا الأخير هو المسؤول عن طريقة كتابة الرسائل. يوجد نوعان من الFormatter الأول هو SimpleFormatter ويقوم بكتابة الرسائل على شكل جمل نصية بسيطة، وXMLFormatter الذي يكتب الرسائل على شكل شجرة xml

سنستعمل SimpleFormatter في المثال

handler.setFormatter(new SimpleFormatter());

الآن وبعد جهد جهيد :wacko: حصلنا على Logger مجهز بشكل جيد وجاهز للبدء في العمل، بقي لنا فقط كتابة الرسائل

عند كتابة كل رسالة يجب تحديد درجة level هذه الرسالة


logger.log(Level.WARNING, "a warning message, something dangerous can happen in any minute, be carefull");
logger.log(Level.INFO, "an information message, something is happening, i just wanted to notice you about it");
logger.log(Level.FINE, "a fine message, some tracing information");
logger.log(Level.FINER, "a finer message, a fairly detailed tracing message");
logger.log(Level.FINEST, "a warning message, a highly detailed tracing message");
 logger.log(Level.SEVERE, "a severe message, something dangerous is happening");

والآن بعدما انتهينا يجب إقفال الHandler

handler.close();

وهذا المثال كاملا


import java.io.IOException;

public class TestLogging {
public static void main(String[] args) {
Logger logger = Logger.getLogger("testlogger");
try {
FileHandler handler = new FileHandler("testlog.log");
logger.addHandler(handler);
handler.setFormatter(new SimpleFormatter());
logger.log(Level.SEVERE, "a severe message, something dangerous is happening");
logger.log(Level.WARNING, "a warning message, something dangerous can happen in any minute, be carefull");
logger.log(Level.INFO, "an information message, something is happening, i just wanted to notice you about it");
logger.log(Level.FINE, "a fine message, some tracing information");
logger.log(Level.FINER, "a finer message, a fairly detailed tracing message");
logger.log(Level.FINEST, "a warning message, a highly detailed tracing message");
handler.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
 import java.util.logging.*;

2
#4

هذا مثال لإستعمال اللوقر ولي عودة لشرح المثال بالتفصيل

أسف على عدم التسيق لأن زر الكود لم يشتغل معي

  1.  
  2.  
  3. import java.io.IOException;
  4. import java.util.logging.FileHandler;
  5. import java.util.logging.Level;
  6. import java.util.logging.Logger;
  7. import java.util.logging.SimpleFormatter;
  8.  
  9. public class MyLogger {
  10.  
  11. public static void main(String[] args) {
  12.  
  13. Logger logger = Logger.getLogger("MyLog");
  14. FileHandler fh;
  15.  
  16. try {
  17.  
  18.  
  19. fh = new FileHandler("c:MyLogFile.log", true);
  20. logger.addHandler(fh);
  21. logger.setLevel(Level.ALL);
  22. SimpleFormatter formatter = new SimpleFormatter();
  23. fh.setFormatter(formatter);
  24.  
  25.  
  26. logger.log(Level.WARNING,"My first log");
  27.  
  28. } catch (SecurityException e) {
  29. e.printStackTrace();
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33.  
  34. }
  35.  
  36. }
  37.  

تم تعديل هذه المشاركة بواسطة طارق إبراهيم في 15 سبتمبر 2009 في 17:01

#5

هذا documentation المرفق للوقر إذا كنت تجيد الإنجليزية فهو سيفيدك كمبتدأ

simple_log_2.0.1.zip

تم تعديل هذه المشاركة بواسطة bilal2005 في 15 سبتمبر 2009 في 17:15

#6

جزاكم الله خيرا

هل بعد هذا السطر

Logger logger = Logger.getLogger("MyLog");

سيتم انشاء ملف باسم

MyLog.Log

???

ثم كيف يمكنني قراءة هذا الملف

او استخراج رسالة قمت بتسجيلها فيه

فمثلا بعد هذا السطر

logger.log(Level.WARNING, "a warning message, something dangerous can happen in any minute, be carefull");

اظهار الرسالة للمستخدم والتعامل مع السطر السابق

وجزاكم الله خيرا

#7

كما قلت، فإن الFileHandler هو المسؤول عن إنشاء الملف والكتابة فيه

يعني بعد هذا السطر

FileHandler handler = new FileHandler("testlog.log");

سيتم إنشاء testlog.log

بالنسبة للسؤال الثاني فالlogs هي ملفات نصية ويمكن أن تقرأها وتستخرج منها ما تريد مثل أي ملف نصي، لا توجد حسب علمي طريقة مباشرة للحصول على رسالة واحدة معينة، يجب أن تقرأ الملف وتستخرجها، طبعا برمجيا

لكن لست متأكدا من النقطة الأخيرة

تم تعديل هذه المشاركة بواسطة herch في 16 سبتمبر 2009 في 14:50

#8

اذا لمادا قاموا بعمل تقنية اللوجر اذا كنت انا استطيع ان اعمل ما تعمله (استطيع عمل وظيفتها ) باستخدام

FileOutPutStream

and

FileInputStream

من خلالهما استطيع كتابة الرسائل التي اريد اضافتها في الملف الذي سأقوم بعمله

؟؟؟؟؟؟؟؟؟؟؟؟

اتمنى ان يتضح الفرق وجزاكم الله خيرا

#9

لا أظن أن المبرمجين في Sun سيضيعون وقتهم في شيء ليست له أي فائدة

أولا تكلمنا عن الHandler، وأعطينا FileHandler كمثال، لكن يوجد أيضا SocketHandler الذي يرسل الرسائل إلى خادم ما وهو يتكفل بها

تكلمنا أيضا عن الFormatter وقلنا أنه يوجد نوعان: SimpleFormatter و XMLFormatter، جرب كتابة شجرة xml برمجيا وتخزينها في ملف لتعرف كم من الجهد وفروا لك بتوفير الكلاس XMLFormatter، وبالمناسبة فإن الXMLFormatter هو الdefault formatter لأي Logger

يمكن أيضا استخدام الlocalization، أي كتابة الرسائل بعدة لغات، هناك طريقة لعمل ذلك باستعمال LogRecord لكني لا أعرفها

هذا مثال يكتب الرسالة حسب لغة الLocale المستعملة، لكنه يستعمل الطريقة العادية وليس LogRecord


import java.io.IOException;
import java.util.*;

public class TestLogging {
public static void main(String[] args) {
Locale arLocale = new Locale("ar"); //arabic locale
Locale enLocale = Locale.UK; //english locale
ResourceBundle bundle = ResourceBundle.getBundle("msg", enLocale);
Logger logger = Logger.getLogger("testlogger");
logger.setUseParentHandlers(false);
try {
FileHandler handler = new FileHandler("testlog.log");
handler.setEncoding("UTF-8");
logger.addHandler(handler);
handler.setFormatter(new SimpleFormatter());
logger.log(Level.SEVERE, bundle.getString("severe"));
logger.log(Level.WARNING, bundle.getString("warning"));
logger.log(Level.INFO, bundle.getString("info"));
handler.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
 import java.util.logging.*;

الملف msg_ar.properties والذي يحتوي على الرسائل بالعربية


warning=\u0625\u0646\u0630\u0627\u0631\u060c \u0634\u064a\u0621 \u062e\u0637\u064a\u0631 \u0639\u0644\u0649 \u0648\u0634\u0643 \u0627\u0644\u062d\u062f\u0648\u062b
info=\u0634\u064a\u0621 \u0645\u0627 \u062d\u0635\u0644
 severe=\u062d\u0635\u0644 \u0634\u064a\u0621 \u062e\u0637\u064a\u0631 \u0641\u064a \u0628\u0631\u0646\u0627\u0645\u062c\u0643

الملف msg_en.properties والذي يحتوي على الرسائل بالإنجليزية


warning=Something dangerous is about to happe
info=Somthing happened
 severe=Something dangerous is happening

#10

جزاك الله خيرا يا

herch على المعلومات القيمة

:rolleyes:

#11

هل هناك handler يخزن في DB?

بدلاً من file

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#12

لا. أظن أنه يجب كتابته يدويا

من يتطوع لكتابته :P

#13

لماذا أحس أنك تقصدني :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#14

بعد شد الشعر والضرب على لوحة المفاتيح وعض أصابعي، تبين أن الأمر ليس بتلك الصعوبة، ويمكن عمل Handler يكتب في قاعدة البيانات

كما قلنا فإن الLogger لا يقوم بالكتابة، بل يمرر الرسائل إلى الHandler، هذا الأخير هو المسؤول عن كتابة الرسائل.

ولنكون أكثر دقة، فإن الLogger ينادي على الميثود publish الخاصة بHandler ويمرر لها object من صنف LogRecord. هذه الكلاس تحتوي على المعلومات الخاصة بالرسالة مثل التاريخ والLevel ونص الرسالة.

من أين يأتي هذا الLogRecord؟؟ عندما ننادي على الميثود log فإن الLogger ينشئ object من صنف LogRecord بالمعلومات التي مررناها للميثود log

المهم، خلاصة القول هي أننا يجب أن نكتب كلاس ترث من Handler وتعيد كتابة الميثود publish بحيث أن الرسالة تخزن في قاعدة البيانات

ملاحظة: في هذه الحالة لن نحتاج إلى Formatter لأننا نحتاجه فقط عند الكتابة في الملفات حيث هو الذي يحدد طريقة كتابة وتنظيم المعلومات داخل الملف

الآن، سيداتي وسادتي، إليكم الكــــــــــــــــــــــــلاااااااااااااااااس DBHandler


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

public class DBHandler extends Handler {

Connection conn;
PreparedStatement st;

public DBHandler() {
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost/MyDB",
"root", "yourPassword");
st = conn.prepareStatement("insert into logs values(?, ?, ?)");
} catch (SQLException ex) {
ex.printStackTrace();
}
}

@Override
public void close() throws SecurityException {
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}

@Override
public void flush() {

}

@Override
public void publish(LogRecord record) {
Timestamp logTime = new Timestamp(record.getMillis());
try {
st.setTimestamp(1, logTime);
st.setString(2, record.getLevel().toString());
st.setString(3, record.getMessage());
st.executeUpdate();
} catch (SQLException ex) {
ex.printStackTrace();
}

}

}
import java.sql.Timestamp;

وهذه الكلاس Main لتجربة الكلاس السابقة


import java.util.logging.Logger;

public class Main {

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Logger logger = Logger.getLogger("testlogger");
DBHandler handler = new DBHandler();
logger.addHandler(handler);
logger.log(Level.SEVERE, "A severe message");
logger.log(Level.WARNING, "A warning message");
logger.log(Level.INFO, "An info message");
handler.close();
}
}
import java.util.logging.Level;

عملت المثال مع MySQL، يعني أولا لازم الdriver الخاص بmysql

استعملت قاعدة بيانات إسمها MyDB، هذه الأخيرة تحتوي على جدول إسمه logs

==============================================================================

بالنسبة للعمود Message فطبعا يجب أن يكون حجمه أكبر من 20، كنت أريد إعطاءه 200 لكن مع التسرع كتبت 20

==============================================================================

post-181903-1253153393_thumb.png

بعد تنفيذ البرنامج، فإن الرسائل تم تخزينها بنجاح في قاعدة البيانات

post-181903-1253153519_thumb.png

طبعا الكلاس ممكن تطويرها، فمثلا الLogRecord يحتوي على معلومات كثيرة أخرى مثل الميثود التي نادت على الLogger وأيضا الكلاس التي تحتوي على هذه الميثود وأشياء أخرى... يكفي قراءة الdocumentaion الخاص بهاته الكلاس

دمتم بخير وإلى اللقاء في الحلقة القادمة بإذن الله :P

تم تعديل هذه المشاركة بواسطة herch في 17 سبتمبر 2009 في 05:24

1
#15

ماشاء الله عليك يا عصام

أنا كنت أفكر في كتابتها اليوم لأني أحتاج لها في العمل

لكن بما أنك كتبتها فسألطشها مباشرة

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#16

ممتاز، لكن طورها أكثر لأنها محتاجة تطوير، فهذه فقط نسخة بسيطة. وبعد ذلك نظم الكود وانشره على شكل api سمها log2db. لكن لا تنس نصيبي من الأرباح :cash:

أظن أن أول شيء يجب تغييره هو جعل الإتصال بالقاعدة يتم في كلاس مستقل، بحيث أن الHandler لا يهتم بقاعدة البيانات التي تستعمل أو كيف يتم الإتصال، المهم عنده هو أن تعطيه object من صنف Connection

هل من متطوع ؟؟

READY.... GOOOOO :lol:

#17

بالتأكيد أنت يا عصام :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#18

:)

165869_381311841924302_17021151_n.jpg

#19

بارك الله فيك اخ عصام ..+2 وجار المذاكره unsure.gif

no-pain-no-gain.jpg

اذا كنت لا تعلم الى اين تذهب... فكــل الطرق تؤدى الى هناك

مواضيع مشابهة