вівторок, 10 червня 2014 р.

Логування в Java (log4j 2)

Мабуть чи не всі програмісти виводять додаткову інформацію на консоль для зневадження програми і просто з метою стеження за її виконанням.  Проміжну інформацію про стан виконання програми, про певні критичні помилки часто корисно записувати у файл чи передати по мережі. Тоді користувач програми може надіслати розробнику звіт і розробник зможе розібратися, що ж пішло не так. Логування у будь-якому разі корисне. Логування у файл можна звичайно зробити самому. Проте навіщо винаходити велосипед, якщо на цьому поприщі вже багато чого зроблено. Існує декілька бібліотек, які спрощують логування. Зараз мова піде про log4j 2-ї версії.

Що потрібно звантажити

* Apache Log4j 2 з оф. сайту (http://logging.apache.org/log4j/2.x/download.html)
* Log4j 2 User’s Guide – посібник користувача (http://logging.apache.org/log4j/2.x/log4j-users-guide.pdf)
* SLF4J – це бібліотека для логування на якій базується log4j 2 (http://www.slf4j.org/download.html)


Підключення бібліотек


Для того щоб наші приклади працювали. Необхідно підключити відповідні *.jar файли до проекту. Не буду пояснювати як це робити.

Розархівовуємо вміст архівів звантажених з інтернету і з них я підключав наступні:

log4j2.0\log4j-api-2.0-rc1.jar
log4j2.0\log4j-core-2.0-rc1.jar
log4j2.0\log4j-slf4j-impl-2.0-rc1.jar
slf4j-1.7.7\integration\lib\slf4j-api-2.0.99.jar
slf4j-1.7.7\integration\lib\slf4j-simple-1.6.99.jar

Якщо не підключити slf4j, то буде видавати помилку виду:

 Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/ILoggerFactory
      at java.lang.ClassLoader.defineClass1(Native Method)...........



Конфігурація Log4j 2

Для того щоб логування працювало як нам потрібно необхідний відповідний файл конфігурації. Можна створити .xml файл, а можна файл properties. Приклади файлів конфігурації можна знайти в посібнику (User’s Guid). Файл повинен бути прописаний в classpath проекту. Можна просто закинути файл у корінь проекту, або у каталог src. Файл конфігурації краще назвати log4j2.xml.

У посібнику користувача можна знайти різні приклади файлу конфігурації для різних цілей: виводу лише на консоль, виводу у файл, виводу у мережевий сокет і т.д. Для виводу у файл матимемо:

<configuration>
    <appenders>
        <file append="false" filename="A1.log" name="A1">
            <patternlayout pattern="%t %-5p %c{6} - %m%n">
        </patternlayout></file>
        <console name="STDOUT" target="SYSTEM_OUT">
            <patternlayout pattern="%d %-5p [%t] %C{6} %M (%F:%L) - %m%n">
        </patternlayout></console>
    </appenders>
    <loggers>
        <logger level="debug" name="org.apache.log4j.xml">
            <appenderref ref="A1">
        </appenderref></logger>
        <root level="debug">
            <appenderref ref="STDOUT">
        </appenderref></root>
    </loggers>
</configuration>

Наступний приклад демонструє роботу з логуванням.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class HelloWorld {
 private static Logger logger = LogManager.getLogger("HelloWorld");

 public static void main(String[] args) {
  logger.info("Hello, world");
  
  Logger fileLog=LogManager.getLogger("org.apache.log4j.xml");
  fileLog.debug("Write in file!");
 }
}

В результаті, якщо був використатий файл конфігурації наведений вище, то на консолі отримаємо:
2014-06-10 15:04:31,610 INFO  [main] HelloWorld (HelloWorld.java:8) - Hello, world
2014-06-10 15:04:31,612 DEBUG [main] HelloWorld (HelloWorld.java:11) - Write in file!
А у файлі:
main DEBUG log4j.xml - Write in file!
Спочатку отримуємо наш основний «Логер», який направлений буде на консоль.

private static Logger logger = LogManager.getLogger("HelloWorld");

Якщо ми хочемо писати у файл щось, то отримуємо логер для файлу:

Logger fileLog=LogManager.getLogger("org.apache.log4j.xml");

І пишемо у файл:

fileLog.debug("Write in file!");

Те як виглядатими наш лог, що туди включатиметься в значній мірі залежить від файла конфігурації.


Можливі передачі у лог і винятків (Exception):

logger.info("Error: ", new Exception("An exception"));


Рівні логування

Не хочеться вдаватися глибоко у цю тему, але необхідно згадати основне. При логуванні розрізняють рівні логування:

1.    TRACE – повідомлення найвищого рівні

2.    DEBUG – зневаджувальні повідомлення, менш детальні ніж TRACE

3.    INFO – стандартні інформаційні повідомлення

4.    WARN – некритичні помилки

5.    ERROR – помилки, що можуть вплинути на правильність результату

6.    FATAL – фатальні помилки, які заважають роботі

За допомогою файлу конфігурації ми можемо вказати, які повідомлення включати у наш лог.  У нас у файлі конфігурації маємо level="debug" . Це означає що на консоль і у файл буде виводитися всі повідомлення рівня Debug і нижче. Повідомлення рівні trace не будуть включатися. Тобто рядок в коді logger.trace("Hello, world"); - нам нічого не виведе ні в лог, ні у файл, ні на консоль, якщо ми не підвищемо рівень логування до TRACE у файлі конфігурації.

Патерни логування

Для формування вигляду логу, використовується відповідний патерн або ж шаблон. У нас використано два патерни, один для файлу інший для консолі.

<PatternLayout pattern="%t %-5p %c{2} - %m%n" />

<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />

%d – вивести дату

%t – ім’я нитки (thread)

%-5p — виводить рівень логу (ERROR, DEBUG, INFO …), цифра 5 означає, що для виводу використовується 5 символів ,  (-), те що вирівнювання буде відбуватися по лівій стороні

%c{1} — виводить назву логера, у фігурних дужках регулюється наскільки повною видаватиметься назва

%L —номер рядка, в якій відбувася виклик запису у лог

%m — повідомлення, що було передано в лог

%n — перехід на новий рядок

Усе це детальніше подато у посібнику користувача.