1. Знайомство з логами

Лог – це список подій, що відбулися. Майже як морський журнал чи щоденник. Ну а логер — це об'єкт, за допомогою якого можна вести логування. У програмуванні прийнято логувати майже все. А в Java — все і навіть трохи більше.

logger java

Справа в тому, що часто Java-програми — це дуже великі серверні програми без UI, консолі, тощо. Вони обробляють одночасно запити тисяч користувачів і часто при цьому виникають різні помилки. Особливо коли різні потоки починають один одному заважати.

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

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

Але чим більше лог, тим складніше з ним працювати. Іноді логи досягають кількох гігабайт на добу. Це нормально.

2.Невдалі логи

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

По-перше, програма може хотіти сама щось вивести в консолі, а користувачу не потрібно бачити службову інформацію, призначену для програміста.

По-друге, розмір буфера консолі обмежений, багато туди не напишеш.

По-третє, інформацію про помилки програми, яка збирається за довгий час, потрібно надіслати розробникам програми. І найзручніше писати всю цю інформацію одразу у файл.

Першу проблему розробники швидко вирішили: вигадали ще один потік виведення — System.err. Ви можете писати в нього повідомлення, і вони будуть надсилатися в окремий потік, а не в стандартну консоль.

І навіть проблему із записом у файл вдалося вирішити:


// Визначаємо файл, до якого будемо писати лог
System.setErr(new PrintStream(new File("log.txt")));
// Виводимо повідомлення
System.err.println("Повідомлення 1");
System.err.println("Повідомлення 2");
// Виводимо повідомлення про помилку
try {
    throw new Exception("Повідомлення про помилку");
} catch (Exception e) {
    e.printStackTrace();
}

Але навіть у такому вигляді це не вирішувало всієї проблеми, тому вирішили створити спеціальну бібліотеку, яка писала б повідомлення лога у файл. Щоб вона робила це розумно і дозволяла гнучко налаштовувати фільтри подій та даних, що логуються.

Весь процес логування по суті складається з трьох частин:

  • Перша частина – це збір інформації.
  • Друга частина – це фільтрування зібраної інформації.
  • Третя частина – це запис відібраної інформації.

3. Знайомство з логером log4j

Першим популярним логером в Java-спільноті став логер log4j. Підключити його до проєкту дуже просто: для цього потрібно додати лише кілька рядків до вашого pom.xml


<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>2.2.17</version>
</dependency>

Взаємодія твоєї програми з таким логером виглядатиме приблизно так:


class Manager {
   private static final Logger logger = LoggerFactory.getLogger(Manager.class);

   public boolean processTask(Task task) {
        logger.debug("processTask id = " + task.getId());
        try {
            task.start();
            task.progress();
            task.complete();
            return true;
        } catch (Exception e) {
            logger.error("Unknown error", e);
            return false;
        }
    }
}

Тут відбуваються три речі:

Зеленим кольором виділено створення об'єкта Logger. Об'єкт зберігається до статичної змінної для зручної роботи з ним. Також до методу getLogger() передається інформація про клас, в якому відбувається збір інформації.

Синім кольором виділено рядок, де ми логуємо інформацію, що має цінність лише під час дебагу. Для цього використовується спеціальний метод – debug()

Ну і нарешті, червоним кольором виділено рядок, де ми зберігаємо в лог виняток, який виник. Винятки – це потенційні помилки, тому для запису в лог використовується метод error().