1.1 Знакомство с логами

Лог – это список произошедших событий. Почти как морской журнал или дневник. Ну а, соответственно, логгер — это объект, с помощью которого можно вести логирование. В программировании принято логировать практически все. А в Java – так вообще все и даже немного больше.

logger java

Дело в том, что Java-программы – это очень часто большие серверные приложения без UI, консоли и так далее. Они обрабатывают одновременно запросы тысяч пользователей и частенько при этом возникают различные ошибки. Особенно, когда разные нити начинают друг другу мешать.

И, фактически, единственным способом поиска редко воспроизводимых ошибок и сбоев в такой ситуации есть запись в лог/файл всего, что происходит в каждой нити.

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

Но чем больше лог, тем сложнее с ним работать. Иногда логи достигают нескольких гигабайт в сутки. Это нормально.

1.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();
}

Но даже в таком виде, это не решало всей проблемы, поэтому было решено создать специальную библиотеку, которая бы писала сообщения лога в файл. Она делала это по-умному и позволяла гибко настраивать фильтры логируемых событий и данных.

Весь процесс логирования, по сути, состоит из трех частей:

  • Первая часть – это сбор информации.
  • Вторая часть – это фильтрование собранной информации.
  • Третья часть – это запись отобранной информации.

1.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().