Java: свертывание многострочных логов в однострочный лог с помощью Spring и логгера Logback или Log4j2

Kate

Administrator
Команда форума
Logback и Log4j2 – одни из самых известных фреймворков логирования в JAVA. Фреймворк Logback используется только совместно с библиотекой SLF4J, которая представляет собой интерфейс для систем протоколирования событий. Log4j2 представляет собой вторую, улучшенную версию логгера Log4, библиотеку логирования, в которой интерфейс API и реализация выделены отдельно, что позволяет использовать API Log4j 2 совместно с реализацией другого логгера.

Spring Music является приложением для использования сервиса базы данных среды Cloud Foundry совместно со Spring Framework и Spring Boot. Оно создано для сохранения одних и тех же доменных объектов в одном из множества различных хранилищ – объектно-реляционном, документно-ориентированном или распределенном (key-value store).

l-hz_yl1hq_kzdyka5tt2vfeac0.jpeg


Двумя наиболее распространенными логгерами, которые используются совместно со Spring / Spring Boot, являются Logback и Log4j2. Еще недавно разработчик имел большую свободу действий в отношении формата логов и самих файлов, используемых для ведения журнала. Однако в современном мире внедрения контейнеров и масштабирования логирование обычно предлагает корпоративные решения, требующие определенного уровня стандартизации.

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

В этой статье рассказывается, как настроить приложение Spring Boot для свертывания исключений в одну строку как для логгера Logback, так и для Log4j2. Это позволяет рассматривать логирование исключения и трассировку стека как один лог событий.

lrdvjed8d9tknggbl67_x-1utt4.jpeg

Классы ошибок Error и исключений Exception в JAVA

wp0teazjqbomtgcorljap3bqoig.jpeg

Проверяемые Checked и непроверяемые Unchecked исключения Exception в JAVA

Приложение Spring Music​


В этой статье для специализированного логирования используется кастомная версия приложения spring-music, необходимая для работы логгеров Logback и Log4j2. Для начала нужно убедиться, что мы сможем воссоздать ее из источника. Проект требует наличия Java8, поэтому первым шагом является установка Java8 на ваш хост Ubuntu.

wyexmd40eutwvvmmwue1w5lek44.jpeg


Затем мы берем исходный код проекта с github и создаем сборку с использованием встроенных скриптов системы сборки Gradle:

cbsqz7dxfedqwrmluhluwjurg6m.jpeg


Свертывание многострочных исключений с использованием Logback​


Двинемся дальше и создадим Java-архив проекта jar с реализацией логгера Logback с помощью стандартной команды Gradle:

2j4awpr_x34ktywzv_6ktimg3us.jpeg


Файл “build/libs/spring-music.jar” является самоисполняемым и содержит встроенный Tomcat, который привязан к localhost:8080. Вызов jar-файла осуществляется с помощью команды:

wk4csj5eugehsudwfdghrilmjrk.jpeg


Вызов http://localhost:8080 в браузере покажет вам страницу со списком Альбомов, а в консоль будет выведена строка лога, выглядящая таким образом:

gzafzavwxyid2nlhpeqxgygk9kc.jpeg


Этот синтаксис строки лога определен в “src/main/resources/logback-spring.xml” с использованием пользовательского шаблона:

w7pxfvjh0rbm8adl-ctlhqs8wf8.jpeg


Переменные ${…} извлекаются из application.properties и system properties, которые можно просмотреть на странице по адресу http://localhost:8080/env. Однако нужная нам часть кода находится сразу после сообщения (%m).

ecoviai9hbwvzt_-bve6nxrq2ps.jpeg


Слово ‘MULTIEXCEPTION’ не имеет особого значения, это просто уникальный строковый маркер, который позволяет нам узнать, где заканчивается сообщение (%m) и начинается исключение. Если хотите, то можете оставить этот маркер.

Далее, вместо того, чтобы просто вставлять заполнитель %xException, который выводил бы большую трассировку стека с символами новой строки, мы преобразуем значение при помощи функции %replace и заменяем все символы новой строки на выражение “\u2028”, которое является представлением разделителя строк Unicode.

Удаление символов "\n" из трассировки стека означает, что теперь трассировка стека теперь будет отправляться в однострочном виде. Чтобы доказать это, перейдите по ссылке http://localhost:8080/errors/throw, где имеется Error Controller, который намеренно отбрасывает NullPointerException с помощью следующего кода:

rv5aqssa51ra4h9l1tbuzxiev3o.jpeg


Это создает в консоли строку лога, показанную ниже:

rbcrzpn1tbfhmhjvqkcyo5xxrxg.jpeg


Здесь видно, что выражение «u2028» отделяет то, что раньше было переводом строки в трассировке стека. Теперь сообщение об исключении и трассировка стека будут отправлены как единое целое.

xujyzcqchwq1l0xiu8ekqgvnupo.jpeg


Свертывание многострочных исключений с использованием Log4j2​


Чтобы переопределить сценарий сборки по умолчанию и использовать Log4j2 в качестве резервной реализации данного проекта, нужно использовать файл “build-log4j2.gradle”.

xujyzcqchwq1l0xiu8ekqgvnupo.jpeg


Файл “build/libs/spring-music.jar” является самоисполняемым и использует встроенный Tomcat, который привязан к localhost:8080. Как и в предыдущем примере, вызов jar-файла осуществляется с помощью команды:

yatetsvficn_m3sqomw1ypprwzq.jpeg


Вызов http://localhost:8080 с помощью браузера отобразит страницу со списком Альбомов с выводом на консоль строки лога, которая выглядит следующим образом:

x-m0qfiewf26kw1dax6qusy9zr8.jpeg


Этот синтаксис строки журнала определен в “src/main/resources/log4j2.xml” с использованием кастомного шаблона:

xj4fttbx2c8px2rcm8pcswuzbbu.jpeg


Переменные ${…} извлекаются из application.properties и system properties, которые можно просмотреть на странице по адресу http://localhost:8080/env. Однако нужная нам часть кода находится сразу после сообщения (%m).

jijsywze7vx1sfdud20-5dvhezg.jpeg


Слово ‘MULTIEXCEPTION’ не имеет специального значения, это просто уникальный строковый маркер по нашему выбору, который позволяет узнать, где заканчивается сообщение (%m) и начинается исключение. Если хотите, то можете его оставить.

Но после этого вместо того, чтобы просто вставлять заполнитель %xException, который выводил бы большую трассировку стека с символами новой строки, мы преобразуем значение при помощи функции %replace, которая заменяет все символы новой строки выражением “\u2028”, которое является представлением разделителя строк Unicode.

Удаление символов "\n" из трассировки стека означает, что теперь трассировка стека теперь будет отправляться в виде одной строки. Чтобы доказать это, перейдите по ссылке http://localhost:8080/errors/throw, где имеется Error Controller, который намеренно отбрасывает NullPointerException с помощью следующего кода:

f828xxcvqh2ps2ubr15aj6dscly.jpeg


Это создает в консоли строку лога, показанную ниже:

fl9gzgv2yso3zsvpk2acummun28.jpeg


Как можно увидеть, здесь выражение «u2028» отделяет то, что раньше было переводом строки в трассировке стека. Теперь сообщение об исключении и трассировка стека будут отправляться как единое целое.

Выводы​


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

При этом символ Unicode всегда может быть заменен на стороне сбора логов (например, на стороне конвейера для сбора, фильтрации и нормализации логов Logstash) для восстановления сообщения в исходном формате.

Ссылочный материал​



Источник статьи: https://habr.com/ru/company/ua-hosting/blog/482804/
 
Сверху