Ведение журнала является важной частью всех приложений и приносит пользу не только нам, разработчикам, но и пользователям системы, а также сопровождающим ее. Приложения Spring Boot должны собирать соответствующие данные журнала, чтобы помочь нам диагностировать и устранять проблемы и измерять бизнес-показатели.
Фреймворк Spring Boot предварительно настроен с использованием Logback в качестве реализации по умолчанию в его "компетентном" подходе к Spring Framework. В этой статье рассматриваются различные способы настройки ведения журнала в Spring Boot.
Пример кода
Эта статья сопровождается примером рабочего кода на GitHub .
Почему важно журналирование
Решения о том, что и где журналировать, часто носят стратегический характер и принимаются с учетом того, что приложение может работать неправильно в реальных средах. Журналы играют ключевую роль, помогая приложению быстро восстанавливаться после любых таких сбоев и возобновлять нормальную работу.
Делаем ошибки в точках интеграции видимыми
Распределенная природа сегодняшних приложений, построенных с использованием микросервисной архитектуры, вводит множество рабочих частей. Таким образом, естественно можно столкнуться с проблемами из-за временных сбоев в любой из инфраструктурных систем.
Журналы исключений, регистрируемые в точках интеграции, позволяют нам обнаружить основную причину прерывания и позволяют нам предпринимать соответствующие действия для восстановления с минимальным влиянием на работу конечного пользователя.
Диагностика функциональных ошибок в производственой системе
Могут быть жалобы клиентов на неправильную сумму транзакции. Чтобы диагностировать это, нам нужно детализировать наши журналы, чтобы найти последовательность операций, начиная с данных запроса при вызове API до данных ответа в конце работы API обработки.
Анализ истории событий
Записи журнала фиксируют трассу выполнения приложения. Мы обращаемся к этим журналам постфактум, чтобы проанализировать любое нормальное или неожиданное поведение приложения для различных задач.
Мы можем узнать количество пользователей, вошедших в систему в течение определенного временного окна, или сколько пользователей активно используют любую недавно выпущенную функцию, что является ценной информацией для планирования изменений для будущих выпусков.
Мониторинг
Инструменты мониторинга отслеживают журналы в режиме реального времени для сбора важных показателей, полезных как для бизнеса, так и для операций, а также могут быть настроены для подачи сигналов тревоги, когда эти показатели превышают определенные пороговые значения. Разработчики используют журналы для отладки и трассировки и даже для записи важных событий для сборки и тестирования в конвейерах CI / CD.
Конфигурация журнала Spring Boot по умолчанию
Конфигурация ведения журнала по умолчанию в Spring Boot - это реализация Logback на уровне информации для записи вывода на консоль.
Давайте посмотрим на это поведение в действии, создав приложение Spring Boot. Мы создаем минимальное приложение только с веб-зависимостью, используя start.spring.io . Затем мы добавляем несколько операторов журнала в файл класса приложения:
@SpringBootApplication
public class SpringLoggerApplication {
static final Logger log =
LoggerFactory.getLogger(SpringLoggerApplication.class);
public static void main(String[] args) {
log.info("Before Starting application");
SpringApplication.run(SpringLoggerApplication.class, args);
log.debug("Starting my application in debug with {} args", args.length);
log.info("Starting my application with {} args.", args.length);
}
}
После компиляции с помощью Maven или Gradle и запуска полученного файла jar мы можем увидеть, как наши записи журнала печатаются в консоли:
13:21:45.673 [main] INFO io.pratik.springLogger.SpringLoggerApplication - Before Starting application
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.2.RELEASE)
.
.
.
... : Started SpringLoggerApplication in 3.054 seconds (JVM running for 3.726)
... : Starting my application 0
Печатается первый информационный журнал, за ним следует семистрочный баннер Spring, а затем следующий информационный журнал. Записи отладки отключены.
Высокоуровневая конфигурация ведения журнала
Spring Boot предлагает значительную поддержку для настройки ведения журнала в соответствии с нашими требованиями к ведению журнала.
На высоком уровне мы можем изменить параметры командной строки или добавить свойства application.properties
(или application.yml
), чтобы настроить некоторые функции ведения журнала.
Настройка уровня журнала с помощью параметра командной строки
Иногда нам необходимо просмотреть подробные журналы для устранения неполадок в поведении приложения. Для этого мы отправляем желаемый уровень журнала в качестве аргумента при запуске нашего приложения.
java -jar target/springLogger-0.0.1-SNAPSHOT.jar --trace
Это начнет вывод журналов уровня трассировки, отладки, информации, предупреждений и ошибок.
Настройка ведения журнала на уровне пакета
В большинстве случаев нас больше интересует вывод журнала написанного нами кода, а не вывод журнала из таких фреймворков, как Spring. Мы контролируем ведение журнала, указывая имена пакетов в переменной окружения log.level.<package-name>
:
java \\
-jar target/springLogger-0.0.1-SNAPSHOT.jar \\
-Dlogging.level.org.springframework=ERROR \\
-Dlogging.level.io.pratik=TRACE
В качестве альтернативы мы можем указать наш пакет в application.properties
:
logging.level.org.springframework=ERROR
logging.level.io.app=TRACE
Журналирование в файл
Мы можем записывать наши журналы в файл, установив только одно из свойств logging.file.name
или logging.file.path
в нашем application.properties
. По умолчанию для вывода в файл установлен уровень журнала info.
# Output to a file named application.log.
logging.file.name=application.log
# Output to a file named spring.log in path /Users
logging.file.path=/Users
Если заданы оба свойства, только logging.file.name
вступает в силу.
Обратите внимание, что название этих свойств изменилось в Spring 2.2 и далее, но в официальной документации это еще не отражено. Наш пример работает с версией 2.3.2.RELEASE.
Помимо имени файла, мы можем переопределить шаблон ведения журнала по умолчанию с помощью свойства logging.pattern.file
:
# Logging pattern for file
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%
Другие свойства, связанные с файлом журнала:
Свойство | Что это значит | Значение, если не установлено |
---|---|---|
| максимальный общий размер архива журнала до ротации файла | 10 Mb |
| сколько дней должны храниться файлы ротации журналов | 7 дней |
| общий размер архивов журналов. Резервные копии удаляются, когда общий размер архивов журналов превышает этот порог. | не указано |
| принудительная очистка архива журнала при запуске приложения | ложный |
Мы можем применить ту же настройку в отдельном файле конфигурации, как мы увидим в следующем разделе.
Отключение баннера
Spring баннер в верхней части файла журнала не добавляет никакой информации. Мы можем отключить баннер, установив для свойства значение off в application.properties
:
spring.main.banner-mode=off
Изменение цвета вывода журнала в консоли
Мы можем отображать вывод с цветовой кодировкой ANSI, установив spring.output.ansi.enabled
свойство. Возможные значения: ВСЕГДА, ОБНАРУЖЕНИЕ и НИКОГДА.
spring.output.ansi.enabled=ALWAYS
По умолчанию для свойства spring.output.ansi.enabled
установлено DETECT
значение. Цветной вывод действует только в том случае, если целевой терминал поддерживает коды ANSI.
Переключение реализации журналирования
Logback стартер является частью стартера Spring Boot по умолчанию. Мы можем заменить его на реализации log4j или java util, включив их стартеры и исключив стартер по умолчанию spring-boot-starter-loging в pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
Низкоуровневая конфигурация ведения журнала в logback-spring.xml
Мы можем изолировать конфигурацию журнала из приложения, указав конфигурацию logback.xml
или logback-spring.xml
в XML или заводной синтаксиса. Spring рекомендует использовать logback-spring.xml
или, logback-spring.groovy
потому что они более мощные.
Конфигурация по умолчанию состоит из appender
элемента внутри корневого configuration
тега. Шаблон указывается внутри encoder
элемента:
<configuration >
<include
resource="/org/springframework/boot/logging/logback/base.xml" />
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
</configuration>
Ведение журнала с конфигурацией Logback
Если мы установим для debug
свойства в configuration
теге значение true
, мы сможем увидеть значения конфигурации логбэка во время запуска приложения.
<configuration debug="true">
Запуск нашего приложения с этим параметром дает результат, содержащий значения конфигурации Logback, используемого в приложении:
...- About to instantiate appender of type [...ConsoleAppender]
...- About to instantiate appender of type [...RollingFileAppender]
..SizeAndTimeBasedRollingPolicy.. - setting totalSizeCap to 0 Bytes
..SizeAndTimeBasedRollingPolicy.. - ..limited to [10 MB] each.
..SizeAndTimeBasedRollingPolicy.. Will use gz compression
..SizeAndTimeBasedRollingPolicy..use the pattern /var/folders/
..RootLoggerAction - Setting level of ROOT logger to INFO
Отслеживание запросов через микросервисы
Отладка и отслеживание в приложениях микросервисов является сложной задачей, поскольку микросервисы развертываются и запускаются независимо, в результате чего их журналы распределяются во множестве отдельных компонентов.
Мы можем сопоставить наши журналы и запросы трассировки между микросервисами, добавив информацию отслеживания в шаблон ведения журнала в logback-spring.xml
. Пожалуйста, ознакомьтесь с трассировкой в распределенных системах для более подробного объяснения распределенной трассировки.
Агрегирование журналов на сервере журналов
Журналы из разных микросервисов можно собирать в центральном месте. Для Spring Boot нам нужно выводить журналы в формате, совместимом с программным обеспечением агрегирования журналов. Давайте посмотрим на приложение, настроенное для Logstash:
<appender name="LOGSTASH"
class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:4560</destination>
<encoder charset="UTF-8"
class="net.logstash.logback.encoder.LogstashEncoder" />
</appender>
Здесь LogstashEncoder
журналы кодируются в формате JSON и отправляются на сервер журналов по адресу localhost:4560
. Затем мы можем применить различные инструменты визуализации к журналам запросов.
Настройка ведения журнала для разных сред
У нас часто используются разные форматы журналов для локальной и производственной среды выполнения. Профили Spring - это элегантный способ реализовать различное ведение журнала для каждой среды. В этой статье вы можете сослаться на очень хороший пример использования ведения журнала для конкретной среды .
Использование Lombok для ссылки на реализацию журналирования
Просто как подсказка, чтобы сэкономить время на вводе: мы можем использовать аннотацию Lombok, Slf4j
чтобы указать ссылку на на реализацию журналирования:
@Service
@Slf4j
public class UserService {
public String getUser(final String userID) {
log.info("Service: Fetching user with id {}", userID);
}
}
Вывод
В этой статье мы увидели, как использовать ведение журнала в Spring Boot и как настроить его в соответствии с нашими требованиями. Но чтобы в полной мере использовать преимущества, возможности фреймворка по ведению журналов необходимо дополнить надежными и стандартизованными методами ведения журналов в ваших группах разработки.
Эти методы также необходимо будет внедрить с помощью сочетания экспертных оценок и автоматизированных инструментов контроля качества кода. Все вместе взятые гарантирует, что при возникновении производственных ошибок у нас будет максимум информации для диагностики.
Вы можете найти весь исходный код, использованный в статье на Github .