Приветствую, дорогие друзья!
Сегодня я хочу продемонстрировать потрясающий пример того, как Бобина может помочь в очень распространённой ситуации — логирование HTTP запросов и ответов в Spring Boot.
Даже больше! Мы будем логировать только сообщения HTTP в отдельные файлы.
Итак, поехали!
Чтобы активировать логирование HTTP в Spring Boot просто добавьте строку в application.properties
:
logging.level.org.springframework.web=TRACE
Такая конфигурация всё ещё не позволит логировать тело HTTP запроса.
Чтобы активировать логирование тела HTTP запроса, создайте конфигурационный класс:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(100000);
filter.setIncludeHeaders(false);
filter.setAfterMessagePrefix("REQUEST DATA : ");
return filter;
}
}
Теперь, давайте настроим Бобину.
Добавьте зависимость в build.gradle
:
compile "io.infinite:bobbin:2.0.4"
Или в pom.xml
:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.5.6</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>io.infinite</groupId>
<artifactId>bobbin</artifactId>
<version>2.0.4</version>
</dependency>
Создайте файл Bobbin.json
в директории с ресурсами или в рабочей директории приложения:
{
"levels": "['debug', 'info', 'warn', 'error'].contains(level)",
"destinations": [
{
"name": "io.infinite.bobbin.destinations.FileDestination",
"properties": {
"fileName": "\"./LOGS/THREADS/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\""
},
"classes": "className.contains('io.infinite.')"
},
{
"name": "io.infinite.bobbin.destinations.FileDestination",
"properties": {
"fileName": "\"./LOGS/ALL/WARNINGS_AND_ERRORS_${date}.log\""
},
"levels": "['warn', 'error'].contains(level)"
},
{
"name": "io.infinite.bobbin.destinations.ConsoleDestination",
"levels": "['warn', 'error'].contains(level)"
}
]
}
Одной из основных особенностей "Бобины" является то, что она с лёгкостью разделяет вывод логирования в отдельные файлы на основании таких критериев как:
- Уровень сообщения (
debug
,warn
, и т.д.) - Название потока
- Имя класса и пакета
- и т.д.
Так зачем нам утруждать себя, ища наши HTTP логи в файлах, содержащих прочие логи?
Давайте направим HTTP логи Spring Boot в отдельные файлы для нашего удобства!
Добавьте новый destination
в Bobbin.json
:
{
"name": "io.infinite.bobbin.destinations.FileDestination",
"properties": {
"fileName": "\"./LOGS/SPRING_WEB/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\""
},
"classes": "className.contains('org.springframework.web')"
}
Как видно, мы записываем логи от классов, содержащих org.springframework.web
в имени их пакета в директорию "SPRING_WEB"
!
Легко, не правда ли?
Вот так выглядит полная конфигурация Bobbin.json
:
{
"levels": "['debug', 'info', 'warn', 'error'].contains(level)",
"destinations": [
{
"name": "io.infinite.bobbin.destinations.FileDestination",
"properties": {
"fileName": "\"./LOGS/THREADS/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\""
},
"classes": "className.contains('io.infinite.')"
},
{
"name": "io.infinite.bobbin.destinations.FileDestination",
"properties": {
"fileName": "\"./LOGS/ALL/WARNINGS_AND_ERRORS_${date}.log\""
},
"levels": "['warn', 'error'].contains(level)"
},
{
"name": "io.infinite.bobbin.destinations.FileDestination",
"properties": {
"fileName": "\"./LOGS/SPRING_WEB/${threadGroupName}/${threadName}/${level}/${threadName}_${level}_${date}.log\""
},
"classes": "className.contains('org.springframework.web')"
},
{
"name": "io.infinite.bobbin.destinations.ConsoleDestination",
"levels": "['warn', 'error'].contains(level)"
}
]
}
А вот и содержимое самого лог файла .\LOGS\SPRING_WEB\main\http-nio-8089-exec-1\debug\http-nio-8089-exec-1_debug_2019-03-22.log
: Ссылка на github.com, т.к. файл имеет длинные строки
Ещё никогда настройка логирования не была такой простой!
Спасибо за внимание!
Borz
Но зачем, если Logback или Log4J, идущие "из коробки" со Spring Boot уже умеют это?
antonpryamostanov Автор
Не умеют. Точнее, например, Logback может разделять по максимум одному MDC дискриминатору (такому как имя потока), но не более одного на файл.
И используемый SiftingAppender имеет меньше настроект и функционал, чем RollingFileAppender. Например, нельзя настроить архивацию по оригинальному имени файла в SiftingAppender.
В общем, архитектурно и с точки зрения настроек там всё очень печально. Поэтому и была создана Бобина.