How to set Logging Level with application.properties in Spring Boot

How to set Logging Level with application.properties in Spring Boot Техника

Время на прочтение

Ведение журнала является важной частью всех приложений и приносит пользу не только нам, разработчикам, но и пользователям системы, а также сопровождающим ее. Приложения Spring Boot должны собирать соответствующие данные журнала, чтобы помочь нам диагностировать и устранять проблемы и измерять бизнес-показатели.

Фреймворк Spring Boot предварительно настроен с использованием Logback в качестве реализации по умолчанию в его «компетентном» подходе к Spring Framework. В этой статье рассматриваются различные способы настройки ведения журнала в Spring Boot.

Содержание
  1.  Пример кода
  2. 1. Структура каталогов
  3. 3. Настройка через
  4. 5. Стандартный Logback.xml
  5. 6. Логирование в Spring Boot + Profile
  6. 5. Установка Root Level
  7. Навигация по записям
  8. Почему важно журналирование
  9. Делаем ошибки в точках интеграции видимыми
  10. Диагностика функциональных ошибок в производственой системе
  11. Анализ истории событий
  12. Мониторинг
  13. Introduction
  14. Log Messages in Spring Boot
  15. Log Levels in Spring Boot
  16. Configuring Log Levels in Spring Boot
  17. Log Groups
  18. Conclusion
  19. How to Use Logging in Python
  20. The Logging Module
  21. Logging Levels
  22. Configuring Logging
  23. How to Use Logging for Debugging
  24. Python Logging Examples
  25. Basic Logging
  26. Logging to a File
  27. Log Message Formatting
  28. Python Error Logging Using Handler and Formatter
  29. Frequently Asked Questions
  30. What is logging in Python?
  31. What is logging getLogger Python?
  32. Track, Analyze and Manage Errors With Rollbar
  33. Zero Configuration Logging
  34. Spring Boot Logging Levels
  35. Spring Boot Log Format
  36. Spring Boot Log to File and Console
  37. Logback Spring Boot Configuration
  38. Log4J Spring Boot configuration
  39. SLF4J Spring Boot configuration
  40. Track, Analyze and Manage Spring Boot Errors With Rollbar
  41. Вступление
  42. System.err.println
  43. Java.util.logging
  44. Log4j
  45. Commons-logging
  46. Logback
  47. SLF4J
  48. Хочу узнать больше
  49. Заключение
  50. Logging at ROOT Level
  51. Использование Lombok для ссылки на реализацию журналирования
  52. Available Logging Levels
  53. Конфигурация журнала Spring Boot по умолчанию
  54. Logging at Application Package Level
  55. application.properties
  56. logback.xml
  57. Logging at Spring Boot Framework Level
  58. Высокоуровневая конфигурация ведения журнала
  59. Настройка уровня журнала с помощью параметра командной строки
  60. Настройка ведения журнала на уровне пакета
  61. Журналирование в файл
  62. Отключение баннера
  63. Изменение цвета вывода журнала в консоли
  64. Переключение реализации журналирования
  65. Низкоуровневая конфигурация ведения журнала в logback-spring.xml
  66. Ведение журнала с конфигурацией Logback
  67. Отслеживание запросов через микросервисы
  68. Агрегирование журналов на сервере журналов
  69. Настройка ведения журнала для разных сред
  70. Logging at Hibernate Level
  71. Вывод

 Пример кода

Эта статья сопровождается примером рабочего кода на GitHub .

The spring boot logging level allow the application to log in different log levels. The spring boot log level is set to INFO by default. The information and above level logs will be shown in the console window or in a log file. The logging level can be modified at the level of the java package or root level.

Spring boot allows to set logging level using the logging.level property in application.properties or application.yml file. The log level enable debug mode in spring boot application.properties. The spring boot log level root will generate complete application logs. The spring boot default log level is INFO.

The logging level of the spring boot application is set using the logging configuration in the application.properties file. The spring boot logging framework enables a configuration that lets you change the logging level of the application.

Spring Boot also includes a good starting point for logback to customise some of the defaults that you can easily use in the logback.xml file. Logging details can be configured in the xml format with Logback.xml. Logback.xml provides high flexibility to customise logging package, level, pattern, file appender, etc.

How to set Logging Level with application.properties in Spring Boot

Сегодня будем подключать логер SLF4J к написанному ранее проекту Spring Boot и Thymeleaf JAR.

SLF4J (Simple Logging Facade for Java) — библиотека для протоколирования, ставящая своей целью предоставить максимально простой, но при этом мощный фасад для различных систем протоколирования на Java.

1. Структура каталогов

How to set Logging Level with application.properties in Spring Boot

По умолчанию SLF4j уже включен в стартовый пакет Spring Boot

3. Настройка через

Что бы включить логирование, создадим application.properties файл в корне папки resources.

3.1 logging.level – определяет уровень логирования, все логи будут выводиться в консоль.

3.2 logging.file – определяет имя файла для логирования, логи будут писаться как в консоль так и в файл одновременно

3.3 logging.pattern – определяет собственные правила(шаблон) ведения журнала

Аналогичный пример в формате

5. Стандартный Logback.xml

Если не нравится шаблон логирования который предлагает Spring Boot, просто создаем стандартный файл logback.xml в корневой папке resources или корне classpath. Это переопределит шаблон логгера Spring Boot.

6. Логирование в Spring Boot + Profile

Создаем logback-spring.xml в корне classpath, это даст нам возможность использовать фичи шаблонов от Spring Boot.

В примере ниже:

  • Если профиль , пишем в консоль и файл;
  • Если профиль , пишем только в файл;


Для не веб приложений можно переопределить логгер через аргументы при запуске приложения

5. Установка Root Level

Бывают ситуации когда места на серверах довольно мало, у меня была подобная ситуация с приложением у одного африканского банка. Мы можем ограничить уровень логирования

И по аналогии YAML


Почему важно журналирование

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

Делаем ошибки в точках интеграции видимыми

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

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

Диагностика функциональных ошибок в производственой системе

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

Анализ истории событий

Записи журнала фиксируют трассу выполнения приложения. Мы обращаемся к этим журналам постфактум, чтобы проанализировать любое нормальное или неожиданное поведение приложения для различных задач.

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

Мониторинг

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

Introduction

Server logs are an important part of development that record the activities or events that the system is performing at any given point in time.

Spring Boot makes use of Apache Commons’ Logging for its system logs by default. Additionally, by default you can use any of the logging frameworks under the SLF4J API such as Logback (which is the default), Log4J2, and Java Util Logging in Spring Boot.

Application logging is a powerful development tool that is important for production-level support and debugging. Each log entry contains information such as the timestamp, the actual method being called, a custom log message, and other contextual information. Each log entry also includes an identifier called a logging level.

In this tutorial, we’ll take a look at how to perform Logging in Spring Boot, using SLF4J, as well as log levels and the configuration required to customize them, and log groups.

Log Messages in Spring Boot

To enable logging in Spring, import Logger and LoggerFactory from the org.slf4j API library:

 org.slf4j.Logger; org.slf4j.LoggerFactory;

Afterwards, declare a constant to store the logger service by instantiating a logger for the class using LoggerFactory:

 Logger log = LoggerFactory.getLogger(DemoService.class);

This log is usually defined at the very top of the global variable list, since it’s a constant. By providing the class you want to log, it’s fully set up and ready to be called with the provided messages.

 {
}

Note: The most common identifier for the logger is log, though you’ll also see logger in a lot of cases. Really, you’re free to call it whatever you’d like, but log is succinct and saves you from writing a longer name due to frequent calls.

Logging in Spring Boot comprises a few different levels. Every log has a degree of urgency or importance that is associated with a log level. Log levels are configured at runtime and each log request checks the log level to see if the request has equal or higher priority than the log level to be displayed.

If you try logging a message which is considered less important than some threshold, it just won’t be logged.

 { logger.error(); logger.warn(); logger.info(); logger.debug(); logger.trace();
}

If no configurations are set in application.properties or elsewhere, the log level will default to INFO. So if we were to call the method logLevelDisplay(), it would output something like this:

2020-12-20 12:46:35.880 ERROR 47958 --- [nio-8080-exec-1] c.service.DemoService : Error message
2020-12-20 12:46:52.976 WARN 47958 --- [nio-8080-exec-1 c.service.DemoService : Warn message
2020-12-20 12:46:59.104 INFO 47958 --- [nio-8080-exec-1] c.service.DemoService : Info message

The DEBUG and TRACE messages weren’t displayed because the application’s log level is set to INFO, which has a higher priority level than the two.

If the log level was set to ERROR, then only the error message would be displayed since it’s the highest log level of the 5 built-in levels.

This brings us to an important topic — log levels, which deserve an explanation of their own.

Log Levels in Spring Boot

As mentioned before, logging in Spring Boot comprises different levels. For example, Hibernate SQL queries are categorized as DEBUG, which is a low-urgency log level that is mainly invoked for debugging purposes.

  • Successfully updated User information: Updated name John to Jon.
  • NullPointerException: id of User is null

The first log is a general informative type of message while the second log is a NullPointerException message.

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

These logs have different levels of urgency, and distinction between them using log levels is important for filtering out logs that don’t have to be output depending on the circumstance. If there’s a huge error going on, you don’t want it to be cluttered by a bunch of working, low-level INFO logs!

SLF4J provides 5 default logging levels in Spring boot:

ERROR — Error logs are serious issues that affect a significant part of the system or some part of your application has failed to operate. Exceptions are considered ERROR level logs. Other examples of error logs are database connection failures and configuration errors. ERROR logs are the most urgent default log level in SLF4J.

WARN — Warning logs are used to indicate potential problems that might cause errors and should be monitored in case they fail. Of course, the context of a warning is subjective to the developer and the situation so warning logs might vary from system to system.

Дополнительно:  Intel(R) USB 3.0 Root Hub USB devices Drivers

INFOINFO is the default logging level that is set by Spring Boot. If no configurations are made, the log level is automatically set to INFO. These types of logs are information that isn’t normally needed but is useful in situations like production code debugging or determining when certain data is manipulated.

DEBUGDEBUG logs include more detailed, specific information that isn’t needed in normal situations. This is often set as a log level when a developer is trying to deep trace a problem or a bug that is hard to trace.

TRACETRACE is a more granular version of DEBUG. TRACE logs are exhaustive, imagine logging every single operation the system is doing, from starting a service, initializing new variables, and calling methods.

In order of urgency, ERROR is the most urgent while TRACE is the least urgent log. The default log level in Spring Boot is INFO when no manual configuration is set.

Configuring Log Levels in Spring Boot

Log levels can be set in the Spring environment by setting its configurations in application.properties.

To specify a log level for all classes that don’t have their own log level settings, the root logger can be set using logging.level.root.

=
=
=

From this configuration, every class except DemoService and the classes under the com.test classpath will have their log levels set to INFO, while the test classes and DemoService have their own specified log levels.

Log Groups

# Initialize log group=com.test, com.test-prod, com.apptest# Set log level to log group=

With this approach, you won’t have to individually set the log level of all related components all the time.

Conclusion

Knowing about the different log levels is important especially in situations like debugging in production.

Let’s say a major bug has been exposed in production, and the current logs do not have enough information to diagnose the root cause of the problem. By changing the log level to DEBUG or TRACE, the logs will show much-needed information to pinpoint crucial details that may lead towards the fix.

In Spring, the log level configurations can be set in the application.properties file which is processed during runtime. Spring supports 5 default log levels, ERROR, WARN, INFO, DEBUG, and TRACE, with INFO being the default log level configuration.

Logging is used to track events that happen when an application runs. Logging calls are added to application code to record or log the events and errors that occur during program execution. In Python, the logging module is used to log such events and errors.

An event can be described by a message and can optionally contain data specific to the event. Events also have a level or severity assigned by the developer.

Logging is very useful for debugging and for tracking any required information.

How to Use Logging in Python

The Logging Module

The Python standard library contains a logging module that provides a flexible framework for writing log messages from Python code. This module is widely used and is the starting point for most Python developers to use logging.

The logging module provides ways for applications to configure different log handlers and to route log messages to these handlers. This enables a highly flexible configuration that helps to handle many different use cases.

To write a log message, a caller requests a named logger. This logger can be used to write formatted messages using a log level (DEBUG, INFO, ERROR etc). Here’s an example:

import logging
log = logging.getLogger("mylogger")
log.info("Hello World")

Logging Levels

The standard logging levels in Python (in increasing order of severity) and their applicability are:

  • DEBUG — Detailed information, typically of interest when diagnosing problems.
  • INFO — Confirmation of things working as expected.
  • WARNING — Indication of something unexpected or a problem in the near future e.g. ‘disk space low’.
  • ERROR — A more serious problem due to which the program was unable to perform a function.
  • CRITICAL — A serious error, indicating that the program itself may not be able to continue executing.

The default log level is WARNING, which means that only events of this level and above are logged by default.

Configuring Logging

In general, a configuration consists of adding a Formatter and a Handler to the root logger. The Python logging module provides a number of ways to configure logging:

  • Creating loggers, handlers and formatters programmatically that call the configuration methods.
  • Creating a logging configuration file and reading it.
  • Creating a dictionary of config information and passing it to the dictConfig() function.

The official Python documentation recommends configuring the error logger via Python dictionary. To do this logging.config.dictConfig needs to be called which accepts the dictionary as an argument. Its schema is:

  • version — Should be 1 for backwards compatibility
  • disable_existing_loggers — Disables the configuration for existing loggers. This is True by default.
  • formatters — Formatter settings
  • handlers — Handler settings
  • loggers — Logger settings

It is best practice to configure this by creating a new module e.g. settings.py or conf.py. Here’s an example:

import logging.config
MY_LOGGING_CONFIG = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'default_formatter': { 'format': '[%(levelname)s:%(asctime)s] %(message)s' }, }, 'handlers': { 'stream_handler': { 'class': 'logging.StreamHandler', 'formatter': 'default_formatter', }, }, 'loggers': { 'mylogger': { 'handlers': ['stream_handler'], 'level': 'INFO', 'propagate': True } }
}
logging.config.dictConfig(MY_LOGGING_CONFIG)
logger = logging.getLogger('mylogger')
logger.info('info log')

How to Use Logging for Debugging

Besides the logging levels described earlier, exceptions can also be logged with associated traceback information. With logger.exception, traceback information can be included along with the message in case of any errors. This can be highly useful for debugging issues. Here’s an example:

import logging
logger = logging.getLogger(“mylogger”)
logger.setLevel(logging.INFO)
def add(a, b): try: result = a + b except TypeError: logger.exception("TypeError occurred") else: return result
c = add(10, 'Bob')
TypeError occurred
Traceback (most recent call last): File "test.py", line 8, in add result = a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'

The output includes the message as well as the traceback info, which can be used to debug the issue.

Python Logging Examples

Basic Logging

Here’s a very simple example of logging using the root logger with basic config:

import logging
logging.basicConfig(level=logging.INFO)
logging.info('Hello World')
INFO:root:Hello World

The message is printed to the console, which is the default output destination. The printed message includes the level and the description of the event provided in the logging call.

Logging to a File

A very common use case is logging events to a file. Here’s an example:

import logging
logging.basicConfig(level=logging.INFO, filename='sample.log', encoding='utf-8')
logging.info('Hello World')
INFO:root:Hello World

Log Message Formatting

The log message format can be specified using the format argument of logging.basicConfig(). Here’s an example:

import logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s:%(levelname)s:%(message)s')
logging.info('Hello World')
2021-12-09 16:28:25,008:INFO:Hello World

Python Error Logging Using Handler and Formatter

Handlers and formatters are used to set up the output location and the message format for loggers. The FileHandler() class can be used to setup the output file for logs:

import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler('sample.log')
formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.info('Hello World')
2021-12-10 15:49:46,494:INFO:Hello World

Frequently Asked Questions

What is logging in Python?

Logging in Python allows the tracking of events during program execution. Logs are added to application code to indicate the occurrence of certain events. An event is described by a message and optional variable data specific to the event. In Python, the built-in logging module can be used to log events.

Log messages can have 5 levels — DEBUG, INGO, WARNING, ERROR and CRITICAL. They can also include traceback information for exceptions. Logs can be especially useful in case of errors to help identify their cause.

What is logging getLogger Python?

To start logging using the Python logging module, the factory function logging.getLogger(name) is typically executed. The getLogger() function accepts a single argument — the logger’s name. It returns a reference to a logger instance with the specified name if provided, or root if not. Multiple calls to getLogger() with the same name will return a reference to the same logger object.

Any logger name can be provided, but the convention is to use the __name__ variable as the argument, which holds the name of the current module. The names are separated by periods(.) and are hierarchical structures. Loggers further down the list are children of loggers higher up the list. For example, given a logger foo, loggers further down such as foo.bar are descendants of foo.

Track, Analyze and Manage Errors With Rollbar

Error Monitoring with RollbarManaging errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates error monitoring and triaging, making fixing Java errors easier than ever. Sign Up Today!

Logging in Spring Boot is very flexible and easy to configure. Spring Boot uses Apache Commons Logging for internal logging but allows developers to configure the underlying log implementation. Various logging providers are supported through simple configuration.

Spring Boot provides default configurations for Java Util Logging, Log4J2 and Logback. Each logging provider is preconfigured to use console output with optional file output available as well. Spring Boot applications need to collect log data to help troubleshoot and fix issues in code, as well as measure business metrics.

Zero Configuration Logging

Spring Boot auto-tunes the majority of the configuration settings within an application so that developers can focus on the code.

The only required dependency for logging using Spring Boot is Apache Commons Logging. When using Spring Boot 2.x, the spring-boot-starter-logging starter pulls in the spring-jcl module, which contains the Apache Commons Logging provider. If using Spring Boot 1.x, Apache Commons Loggingem> needs to be imported explicitly.

When Spring Boot starters are used, Logback is used for logging by default. The default Logback implementation logs the output to the console at the info level. Logback routing is included as well to ensure support for Apache Commons Logging, Java Util Logging, Log4J and SLF4J.

Spring Boot Logging Levels

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
logging.level.loggername=level

The root logger can be configured using logging.level.root.

Here is an example for configuring the root logging level in the application.properties file:

logging.level.root = WARN
Logging.level.org.springframework.web = DEBUG

It is also possible to set the logging level using environment variables. For example, LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB = ERROR will set org.springframework.webR logging level to ERROR.

Spring Boot Log Format

The default Spring Boot log format is shown below:

2021-07-08 13:25:09.187 INFO 9769 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-07-08 13:25:09.198 INFO 9769 --- [main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-07-08 13:25:09.198 INFO 9769 --- [main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.48]
2021-07-08 13:25:09.276 INFO 9769 --- [main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-07-08 13:25:09.276 INFO 9769 --- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1005 ms
2021-07-08 13:25:09.616 INFO 9769 --- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
  • Date and Time
  • Log level (TRACE, DEBUG, INFO, WARN or ERROR)
  • Process ID
  • The separator — to distinguish the start of the log message
  • Thread name enclosed within square brackets []
  • Logger name showing the source class
  • Log message

The log format can be customized using the logging.pattern.console and logging.pattern.file properties in application.properties, for example:

# Logging pattern for the console
logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n
# Logging pattern for file
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%
2021-07-08 13:41:04 - o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
2021-07-08 13:41:04 - o.a.catalina.core.StandardService - Starting service [Tomcat]
2021-07-08 13:41:04 - o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.48]
2021-07-08 13:41:04 - o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2021-07-08 13:41:04 - o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 955 ms
2021-07-08 13:41:04 - o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''

Spring Boot Log to File and Console

Spring Boot logs to only the console by default. File logging is supported and can be enabled using the logging.file or logging.path properties in application.properties.

The log file path can be specified using the logging.path property as shown below. When using this property, a file named spring.log will be created in the specified location:

logging.path = /tmp/

The log file name can be specified using the logging.filecode> property:

logging.file = /tmp/application.log

Logback Spring Boot Configuration

  • logback-spring.xml
  • logback.xml
  • logback-spring.groovy
  • logback.groovy

The -spring variant is recommended whenever possible.

Дополнительно:  Что делать, если не работает клавиатура на ноутбуке или компьютере

Here is an example of a simple logback-spring.xml implementation:

<----?xml version="1.0" encoding="UTF-8"?----> %d{yyyy-MM-dd HH:mm} - %logger{36} - %msg%n ${LOGS}/application.log %d{yyyy-MM-dd HH:mm} - %logger{36} - %msg%n ${LOGS}/archived/application-%d{yyyy-MM-dd}.%i.log 10MB 

Here is the output when the application is run with the above configuration:

2021-07-08 14:40 - o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
2021-07-08 14:40 - o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]
2021-07-08 14:40 - o.a.catalina.core.StandardService - Starting service [Tomcat]
2021-07-08 14:40 - o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.48]
2021-07-08 14:40 - o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
2021-07-08 14:40 - o.s.b.w.s.c.ServletWebServerApplicationContext - Root WebApplicationContext: initialization completed in 1026 ms
2021-07-08 14:40 - o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
2021-07-08 14:40 - o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''

Log4J Spring Boot configuration

Spring Boot includes routing to other logging frameworks to make it easy to switch to them. To be able to use any other logging framework, Logback needs to be excluded from the application dependencies. Also, the alternative library or starter (in this case spring-boot-starter-log4j2) needs to be added to the classpath:

<---dependency--->
org.springframework.boot
spring-boot-starter-web
<---exclusions--->
<---exclusion--->
org.springframework.boot
spring-boot-starter-logging
<---/exclusion--->
<---/exclusions--->
<---/dependency--->
<---dependency--->
org.springframework.boot
spring-boot-starter-log4j2
<---/dependency--->
  • log4j2-spring.xml
  • log4j2.xml

Here is an example of a simple log4j2-spring.xml implementation:

<---?xml version="1.0" encoding="UTF-8"?--->
<---Configuration---> <---Properties---> <---Property name="LOGS">./logs<---/Property---> <---Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm} %p %m%n<---/Property---> <---/Properties--->
<---/Configuration--->

Here is the output when the application is run with the above configuration:

2021-07-10 15:20 INFO Tomcat initialized with port(s): 8080 (http)
2021-07-10 15:20 INFO Initializing ProtocolHandler ["http-nio-8080"]
2021-07-10 15:20 INFO Starting service [Tomcat]
2021-07-10 15:20 INFO Starting Servlet engine: [Apache Tomcat/9.0.48]
2021-07-10 15:20 INFO Initializing Spring embedded WebApplicationContext
2021-07-10 15:20 INFO Root WebApplicationContext: initialization completed in 853 ms
2021-07-10 15:20 INFO Starting ProtocolHandler ["http-nio-8080"]
2021-07-10 15:20 INFO Tomcat started on port(s): 8080 (http) with context path ''

SLF4J Spring Boot configuration

Log4j2 can be configured to be used with or without SLF4J. To use it, the SLF4J logger classes org.slf4j.Logger and org.slf4j.LoggerFactory can be used in application code and all log statements will output the logs to the target appenders

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SpringBootApplication
public class DemoApplication { private static final Logger LOGGER = LoggerFactory.getLogger(DemoApplication.class); public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }
}

To use Log4j2 natively without SLF4J, the log4j2 native logger classes org.apache.logging.log4j.Logger and org.apache.logging.log4j.LogManager can be used:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@SpringBootApplication
public class DemoApplication { private static final Logger LOGGER = LogManager.getLogger(DemoApplication.class); public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }
}

No other modification needs to be made in the Log4j2 Spring Boot configuration.

Track, Analyze and Manage Spring Boot Errors With Rollbar

Rollbar in action

Managing errors and exceptions in your code is challenging. It can make deploying production code an unnerving experience. Being able to track, analyze, and manage errors in real-time can help you to proceed with more confidence. Rollbar automates Spring Boot error monitoring and triaging, making fixing errors easier than ever. Try it today.

Время на прочтение

Вступление

Думаю, ни для кого не секрет, что такое логгеры и для чего они нужны. За время существования java было создано немало фреймворков логгирования. Среди самых известных можно выделить:

  • JUL — java.util.logging
  • log4j
  • JCL — jakarta commons logging
  • Logback
  • SLF4J — simple logging facade for java

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

System.err.println

// Определяем файл в который будем писать лог
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();
}

Java.util.logging

Данный фреймворк включен в стандарт и поставляется вместе с JDK, поэтому ничего дополнительно скачивать и подключать вам не надо. JUL имеет следующие уровни логгирования по возрастанию: FINEST, FINER, FINE, CONFIG, INFO, WARNING, SEVERE, а так же ALL и OFF, включающий и отключающий все уровни соответственно.
Логгер создается вызовом одного из статических методов класса java.util.logging.Logger:

Logger log = Logger.getLogger(LoggingJul.class.getName());

Методы логгера могут принимать в качестве аргументов строковые сообщения, шаблоны сообщений, исключения, ресурсы локализованных текстовок сообщений, а также, начиная с Java 8, поставщиков строковых сообщений:

// Строковое сообщение
String stringMessage = "Сообщение";
// Строковое сообщение с параметрами
String stringMessageFormat ="Сообщение {0}";
// Исключение
Throwable throwable = new Throwable();
// ResourceBundle хранящий сообщения
ResourceBundle resourceBundle = ResourceBundle.getBundle("logging.jul.bundle");
// Поставщик сообщений
Supplier<String> stringMessageSupplier = ()->"Сообщение";

Выделяется две группы методов: название которых соответствует уровню логгирования и методы log, loggp, logrb, принимающие уровень логгирования в качестве параметра с типом Level. Первая группа содержит методы двух типов: принимающих строковое сообщение или поставщика строковых сообщений:

log.info(stringMessage);
log.info(stringMessageSupplier);

Вторая группа методов имеет следующие вариации:

// Вывести сообщение с указанием уровня логгирования
log.log(new LogRecord(Level.INFO, stringMessage));
log.log(Level.INFO, stringMessage);
log.log(Level.INFO, stringMessageSupplier);
log.log(Level.INFO, stringMessageFormat, args);
log.log(Level.INFO, stringMessage, throwable );
log.log(Level.INFO, throwable, stringMessageSupplier);
// Вывести сообщение с указанием уровня логгирования, класса и метода
log.logp(Level.INFO, "ClassName", "MethodName", stringMessage);
log.logp(Level.INFO, "ClassName", "MethodName", stringMessageSupplier);
log.logp(Level.INFO, "ClassName", "MethodName", stringMessageFormat, args);
log.logp(Level.INFO, "ClassName", "MethodName", stringMessage, throwable);
log.logp(Level.INFO, "ClassName", "MethodName", throwable, stringMessageSupplier);
// Вывести сообщение с указанием уровня логгирования, класса,
// метода и resourceBundle, хранящего сообщения
log.logrb(Level.INFO, "ClassName", "MethodName", resourceBundle, "messageId");
log.logrb(Level.INFO, "ClassName", "MethodName", resourceBundle, "messageId", throwable);
// Вывести сообщение об ошибке
log.throwing("ClassName","MethodName", throwable);

Теперь обратимся к конфигурации фреймворка. По умолчанию JUL будет выводить сообщения на консоль, однако можно задать конфигурацию в файле свойств. Для задания способа вывода сообщений необходимо для вашего логгера указать какие хендлеры он будет использовать. Существует следующие классы хендлеров: FileHandler, ConsoleHandler, StreamHandler, SocketHandler, MemoryHandler. Особенностью JUL является то, что настройки хендлеров задаются в целом для всего класса, а не для конкретного экземпляра, что может порождать не мало проблем, например если вам потребуется сообщения различных логгеров выводить в различные файлы или с различным форматированием. Рассмотрим простой пример конфигурационного файла:

# Настройки глобального логгера
handlers =java.util.logging. FileHandler
.level=ALL
# Конфигурация файлового хендлера
java.util.logging.FileHandler.level =ALL
java.util.logging.FileHandler.formatter =java.util.logging.SimpleFormatter
java.util.logging.FileHandler.limit = 1000000
java.util.logging.FileHandler.pattern = log.txt
# Конфигурация консольного хендлера
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.pattern = log.log
java.util.logging.ConsoleHandler.formatter =java.util.logging.SimpleFormatter

Для того что бы JUL применил данную конфигурацию нужно передать параметр -Djava.util.logging.config.file = <путь до файла>, либо при старте приложения выполнить код:

LogManager.getLogManager().readConfiguration(<ваш класс>.class.getResourceAsStream("logging.properties"));

Log4j

Данный фреймворк на текущий момент имеет уже вторую версию, которая увы не совместима с первой. Поскольку первая версия log4j существует достаточно давно и, в виду ее большой популярности, существует не мало статей на просторах интернета, сегодня мы рассмотрим вторую. Для использования log4j2 вам необходимо подключить библиотеки log4j-api-2.x и log4j-core-2.x. Log4j имеет несколько отличное от JUL именование уровней логгирования: TRACE, DEBUG, INFO, WARN, ERROR, FATAL, а так же ALL и OFF включающий и отключающий все уровни соответственно.
Логгер создается вызовом статического метода класса org.apache.logging.log4j.Logger:

Logger log = LogManager.getLogger(LoggingLog4j.class);
// или
Logger log = LogManager.getLogger(“name”);

Логгер умеет принимать помимо привычных нам String, Object и Throwable еще два новых типа — MapMessage и Marker:

// Карта сообщений (напечатается как msg1="Сообщение 1” msg2="Сообщение 2”)
MapMessage mapMessage = new MapMessage();
mapMessage.put("msg1", "Сообщение 1");
mapMessage.put("msg2", "Сообщение 2");
// Маркер, объект по которому можно фильтровать сообщения
Marker marker = MarkerManager.getMarker("fileonly");
// Строковое сообщение
String stringMessage = "Сообщение";
// Строковое сообщение с параметрами
String stringMessageFormat = "Сообщение {}, от {}";
// Исключение
Throwable throwable = new Throwable();
// Объект
Object object = new Object();

В классическом для логгеров стиле методы делятся на два типа: совпадающие с названием уровня логгирования и методы log, принимающие уровень логгирования в качестве параметра. Первые имеют вид:

log.info(mapMessage);
log.info(object);
log.info(stringMessage);
log.info(marker, mapMessage);
log.info(marker, object);
log.info(marker, stringMessage);
log.info(object, throwable);
log.info(stringMessage, throwable);
log.info(stringMessageFormat, args);
log.info(marker, mapMessage, throwable);
log.info(marker, object, throwable);
log.info(marker, stringMessageFormat, args);
log.info(marker, stringMessage, throwable);
log.throwing(throwable);

Методы log в log4j2 выглядят так:

log.log(Level.INFO, mapMessage);
log.log(Level.INFO, object);
log.log(Level.INFO, stringMessage);
log.log(Level.INFO, marker, mapMessage);
log.log(Level.INFO, marker, object);
log.log(Level.INFO, marker, stringMessage);
log.log(Level.INFO, object, throwable);
log.log(Level.INFO, stringMessageFormat, args);
log.log(Level.INFO, stringMessage, throwable);
log.log(Level.INFO, marker, mapMessage, throwable);
log.log(Level.INFO, marker, object, throwable);
log.log(Level.INFO, marker, stringMessageFormat, args);
log.log(Level.INFO, marker, stringMessage, throwable);
log.throwing(Level.INFO, throwable);

Если не определить конфигурацию, то при запуске log4j2 выдаст гневное сообщение, о том, что конфигурация не задана и будет печатать ваши сообщения на консоль уровнем не ниже ERROR. Конфигурация log4j2 задается несколькими вариантами: xml, json, yaml. Стоит отметить, что со второй версии нет поддержки конфигурации из property файла. Файл с конфигурацией автоматически ищется classpath, должен иметь название log4j2 и располагаться в пакете по умолчанию.
Конфигурация log4j2 состоит из описания логгеров, аппендеров и фильтров. Для более детального изучения обратитесь к документации, сейчас же лишь отметим пару ключевых моментов. Во-первых, есть различные вкусности в виде фильтров, в том числе и по маркерам:

  • BurstFilter
  • CompositeFilter
  • DynamicThresholdFilter
  • MapFilter
  • MarkerFilter
  • RegexFilter
  • StructuredDataFilter
  • ThreadContextMapFilter
  • ThresholdFilter
  • TimeFilter

Во-вторых, имеется широкий круг классов аппендеров, в том числе асинхронные аппендеры и аппендеры оборачивающие группу других аппендеров:

Стоит также заметить, что log4j может создавать множество различающихся аппендеров одного и того же класса, например несколько файловых аппендеров, которые пишут в разные файлы.
Рассмотрим пример конфигурации, в которой объявлены два логгера (корневой и для нашего класса), первый из которых пишет в файл log.log, а второй пишет в log2.log с использованием фильтрации по маркеру:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration> <!-- Секция аппендеров --> <Appenders> <!-- Файловый аппендер --> <File name="file" fileName="log.log"> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern> </PatternLayout> </File> <!-- Файловый аппендер --> <File name="file2" fileName="log2.log"> <!-- Фильтр по маркеру --> <MarkerFilter marker="fileonly" onMatch="DENY" onMismatch="ACCEPT"/> <PatternLayout> <Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern> </PatternLayout> </File> </Appenders> <!-- Секция логгеров --> <Loggers> <!-- Корневой логгер --> <Root level="trace"> <AppenderRef ref="file" level="DEBUG"/> </Root> <!-- Логгер нашего класса --> <Logger name="logging.log4j.LoggingLog4j" level="info" additivity="false"> <AppenderRef ref="file2" level="INFO"/> </Logger> </Loggers>
</Configuration> 

Commons-logging

Довольно старый проект, который представляет собой обертку над JUL и log4j, не привносящая никакого дополнительного функционала. Уровни логгирования у JCL совпадают с log4j, а в случае взаимодействия с JUL происходит следующее сопоставление:

fatal = Level.SEVERE
error = Level.SEVERE
warn = Level.WARNING
info = Level.INFO
debug = Level.FINE
trace = Level.FINEST

Для использования JCL подключаем commons-logging-1.x.jar. Создаем логгер вызовом метода фабрики:

Log log = LogFactory.getLog(LoggingCl.class);
// или
Log log = LogFactory.getLog("name");

Методы JCL очень простые, совпадают с названием уровней логгирования, принимают только объекты и исключения и имеют две вариации:

Object object = "Сообщение";
Throwable throwable = new Throwable();
log.info(object);
log.info(object, throwable);

Конфигурация JCL содержит отдельные блоки для log4j, JUL и собственной реализации. Если не задать конфигурацию, то используется собственная реализация, именуемая SimpleLog, которая выводит сообщения на консоль. Рассмотрим пример конфигурационного файла:

#Log4j
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
log4j.configuration=log4j.properties
#JUL
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level=INFO
java.util.logging.FileHandler.pattern=jul.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.limit=50000
java.util.logging.FileHandler.count=1
#SimpleLog
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog
org.apache.commons.logging.simplelog.defaultlog=fatal
org.apache.commons.logging.simplelog.showlogname=true
org.apache.commons.logging.simplelog.showShortLogname=true
org.apache.commons.logging.simplelog.showdatetime=true

Указать файл конфигурации JCL можно следующим образом:

java -Djava.util.logging.config.file=/absolute/path/to/your/config/file/commons-logging.properties -jar /absolute/path/to/your/jar/file/MyClass.jar

Logback

Данный фреймворк используется только в связке с оберткой SLF4J, которую мы будем рассматривать позднее. Для начала работы вам необходимы logback-core-1.x.jar и logback-classic-1.x.x.jar, а также slf4j-api-1.x.x.jar.
Взаимодействие с логгером мы будем осуществлять через API предоставляемый оберткой SLF4J. Уровни логгирования совпадают с log4j. Создание логгера в таком случае выглядит следующим образом:

org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggingLogback.class);
// или
org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("name");

API позволяет выводить строковые сообщения, шаблоны строковых сообщений, исключения, а также использовать маркеры:

// Строковое сообщение
String stringMessage = "Сообщение";
// Шаблон сообщения
String stringMessageFormat = "Сообщение {} {}";
// Ошибка
Throwable throwable = new Throwable();
// Маркер
Marker marker = MarkerFactory.getMarker("marker");

Названия методов совпадают с уровнями логгирования и имеют вид:

log.info(stringMessage);
log.info(stringMessageFormat, args);
log.info(stringMessage, throwable);
log.info(marker, stringMessage);
log.info(marker, stringMessage, throwable);
log.info(marker,stringMessageFormat, args);

Теперь рассмотрим непосредственны функционал logback. Конфигурация ищется в classpath в следующем порядке:

  1. Пытается найти logback.groovy
  2. Иначе пытается найти logback-test.xml
  3. Иначе пытается найти logback.xml
  4. Иначе использует базовую конфигурацию — выводим сообщения на консоль

Основными элементами конфигурации являются логгеры, аппендеры, лайауты, и фильтры.
Имеются следующие фильтры:

  • Regular filters
  • LevelFilter
  • ThresholdFilter
  • EvaluatorFilter
  • Matchers
  • TurboFilters
  • CountingFilter

Имеются следующие аппендеры:

  • OutputStreamAppender
  • ConsoleAppender
  • FileAppender
  • RollingFileAppender
  • SocketAppender and SSLSocketAppender
  • ServerSocketAppender and SSLServerSocketAppender
  • SMTPAppender
  • SyslogAppender
  • SiftingAppender
  • AsyncAppender

О том что такое Layouts и Encoders в logback предлагаю прочитать подробно в документации, а сейчас лишь приведу простой пример файла logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration> <!--Аппендеры --> <!--Файловый аппендер --> <appender name="file" class="ch.qos.logback.core.FileAppender"> <file>log.log</file> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern> </layout> </appender> <!--Консольный аппендер --> <appender name="sout" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </layout> </appender> <!-- Фильтры --> <!-- Фильтр по маркеру --> <turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter"> <Marker>marker</Marker> <OnMatch>DENY</OnMatch> </turboFilter> <!-- Логгеры --> <!-- Корневой логгер --> <root level="info"> <appender-ref ref="file" /> </root> <!-- Логгер нашего класса --> <logger name="logging.logback.LoggingLogback" level="info" > <appender-ref ref="sout" /> </logger>
</configuration>

SLF4J

Как уже говорилось ранее SLF4J является оберткой над logback, а также над JUL, log4j, или JCL, а также над любым логгером, который реализует ее интерфейс. Для работы с SLF4J нужны библиотека slf4j-api-1.x.x.jar и реализация одного из логгеров либо заглушка. Как правило реализации всех логгеров ( кроме logback) поставляются вместе с SLF4J и имеют названия на подобии slf4j-jcl-1.x.jar, slf4j-log4j12-1.x.jar, slf4j-nop-1.x.jar и т.п. Если в classpath не будет найдена реализация логгера ( или заглушка nop) SLF4J гневно ругнется и работать откажется. Конфигурация соответственно будет искаться в зависимости от положенной в classpath реализации.
API SLF4J мы рассмотрели в предыдущем пункте, поэтому давайте рассмотрим еще одну возможность обертки. В идеальном мире мы должны выводить сообщения через интерфейс обертки, и тогда у нас все будет хорошо, но реальный жестокий мир говорит о том, что всем нам приходится взаимодействовать со сторонними библиотеками или кодом, в которых используются другие логгеры и которые знать не знают о SLF4J. Что бы не подстраиваться под каждый логгер, а пустить все сообщения через одну реализацию интерфейса SLF4J, можно использовать bridging. В поставке обертки содержаться библиотеки jcl-over-slf4j.jar, log4j-over-slf4j.jar и jul-to-slf4j.jar, которые переопределяют поведение соответствующих логгеров и перенаправляют сообщения в обертку.
Что бы стало понятнее выше сказанное, рассмотрим пример. Допустим у нас имеются следующие логгеры:

java.util.logging.Logger julLog = java.util.logging.Logger.getLogger("julLog");
java.util.logging.Logger log4jLog = java.util.logging.Logger.getLogger("log4jLog");
org.slf4j.Logger slf4jLog = org.slf4j.LoggerFactory.getLogger(LoggingSlf4j.class);
julLog.info("Сообщение от jul");
log4jLog.info("Сообщение от log4j");
slf4jLog.info("Сообщение от slf4j");

Мы хотим, что бы сообщение от JUL записывались в один файл, от log4j в другой, а от slf4j выводились на консоль. В качестве реализации обертки будем использовать logback, конфигурация сего безобразия будет выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<configuration> <!--Аппендеры --> <!--Файловый аппендер для JUL --> <appender name="jul" class="ch.qos.logback.core.FileAppender"> <file>log_jul.log</file> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern> </layout> </appender> <!--Файловый аппендер для log4j --> <appender name="log4j" class="ch.qos.logback.core.FileAppender"> <file>log_log4j.log</file> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</Pattern> </layout> </appender> <!--Консольный аппендер --> <appender name="sout" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern> </layout> </appender> <!-- Логгеры --> <!-- Корневой логгер --> <root level="info" > <appender-ref ref="sout" /> </root> <!-- Логгер для jul --> <logger name="julLog" additivity="false" > <level value="trace" /> <appender-ref ref="jul" /> </logger> <!-- Логгер для log4j --> <logger name="log4jLog" additivity="false" > <level value="trace" /> <appender-ref ref="log4j" /> </logger>
</configuration>

Для того, что бы мост заработал необходимо выполнить код:

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

Хочу узнать больше

  • JUL — читать Java Logging: Logger и Java Logging: Configuration
  • Log4j2 — читать Welcome to Log4j 2
  • JCL- читать How to use Commons Logging
  • Logback- читать The logback manual
  • SLF4J — читать SLF4J documentation и Bridging legacy APIs
Дополнительно:  Unlock root pro что это

Заключение

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

Logging at ROOT Level

Logging at the root level configuration can be extended to the whole application. This logging level would extend to both java packages and jar files. This logs are typically very large in volume. The root level log is usually configured with the WARN level to restrict the logs to be created at the root level.

logging.level.root=WARN
logging.level.web=DEBUG
logging.level.sql=DEBUG

Использование Lombok для ссылки на реализацию журналирования

Просто как подсказка, чтобы сэкономить время на вводе: мы можем использовать аннотацию Lombok, Slf4jчтобы указать ссылку на на реализацию журналирования:

@Service
@Slf4j
public class UserService { public String getUser(final String userID) { log.info("Service: Fetching user with id {}", userID); }
}

Available Logging Levels

There are seven types of logging levels available in the spring boot logging framework. Logging level works as a relative level. If the logging level is set to info, info logs and above level logs will be seen. In this scenario, all INFO, WARN, ERROR, FATAL logs will be seen.

TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF

Конфигурация журнала 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, а затем следующий информационный журнал. Записи отладки отключены.

Logging at Application Package Level

The spring boot application has been created with the custom package name. The logging level can be changed for the application package level. The logs within the custom package will be application for the logging level configuration. For each package name, the logging level may be configured differently. If the logging level is set in the root package, it will be applied to all subpackages.

application.properties

logging.level.com.yawintutor=DEBUG

logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
........... <logger name="com.yawintutor" level="DEBUG" additivity="false"> <appender-ref ref="RollingFile" /> <appender-ref ref="Console" /> </logger>
...........
</configuration>

Logging at Spring Boot Framework Level

Spring boot framework files will be included in the package starting with org.springframework. If the logging level is modified using this package, the logs of the spring boot framework will be displayed at the configured logging level.

logging.level.org.springframework=DEBUG
logging.level.org.springframework.web=DEBUG

Высокоуровневая конфигурация ведения журнала

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%

Другие свойства, связанные с файлом журнала:

Мы можем применить ту же настройку в отдельном файле конфигурации, как мы увидим в следующем разделе.

Отключение баннера

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 — это элегантный способ реализовать различное ведение журнала для каждой среды. В этой статье вы можете сослаться на очень хороший пример использования ведения журнала для конкретной среды .

Logging at Hibernate Level

The most important logs in the spring boot framework are to debug the hibernate level to understand the execution queries. The generated sql and parameter values are printed using hibernate logs. Setting the hibernate logging level is critical for the spring boot application to match the number of logs and log information.

spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate=DEBUG
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql=DEBUG

Вывод

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

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

Вы можете найти весь исходный код, использованный в статье на Github .

Оцените статью
Master Hi-technology