- Логирование HTTP запросов в Spring Boot с использованием Бобины
- Logging Practices
- Context Logging
- Wire Logging
- HTTP header Logging
- Configuration Examples
- Commons Logging Examples
- Log4j 2 Examples
- java.util.logging Examples
- Logging Practices
- Understanding Logger Names
- Context Logging
- Wire Logging
- HTTP header Logging
- Configuration Examples
- Log4j 2 Examples
Логирование HTTP запросов в Spring Boot с использованием Бобины
Сегодня я хочу продемонстрировать потрясающий пример того, как Бобина может помочь в очень распространённой ситуации — логирование 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"
org.codehaus.groovy groovy-all 2.5.6 pom io.infinite bobbin 2.0.4
Создайте файл Bobbin.json в директории с ресурсами или в рабочей директории приложения:
< "levels": "['debug', 'info', 'warn', 'error'].contains(level)", "destinations": [ < "name": "io.infinite.bobbin.destinations.FileDestination", "properties": < "fileName": "\"./LOGS/THREADS/$/$/$/$_$_$.log\"" >, "classes": "className.contains('io.infinite.')" >, < "name": "io.infinite.bobbin.destinations.FileDestination", "properties": < "fileName": "\"./LOGS/ALL/WARNINGS_AND_ERRORS_$.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/$/$/$/$_$_$.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/$/$/$/$_$_$.log\"" >, "classes": "className.contains('io.infinite.')" >, < "name": "io.infinite.bobbin.destinations.FileDestination", "properties": < "fileName": "\"./LOGS/ALL/WARNINGS_AND_ERRORS_$.log\"" >, "levels": "['warn', 'error'].contains(level)" >, < "name": "io.infinite.bobbin.destinations.FileDestination", "properties": < "fileName": "\"./LOGS/SPRING_WEB/$/$/$/$_$_$.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, т.к. файл имеет длинные строки
Ещё никогда настройка логирования не была такой простой!
Logging Practices
Being a library HttpClient is not to dictate which logging framework the user has to use. Therefore HttpClient utilizes the logging interface provided by the Commons Logging package. Commons Logging provides a simple and generalized log interface to various logging packages. By using Commons Logging , HttpClient can be configured for a variety of different logging behaviours. That means the user will have to make a choice which logging framework to use. By default Commons Logging supports the following logging frameworks:
By implementing some simple interfaces Commons Logging can be extended to support basically any other custom logging framework. Commons Logging tries to automatically discover the logging framework to use. If it fails to select the expected one, you must configure Commons Logging by hand. Please refer to the Commons Logging documentation for more information.
HttpClient performs three different kinds of logging: the standard context logging used within each class, HTTP header logging and full wire logging.
Context Logging
Context logging contains information about the internal operation of HttpClient as it performs HTTP requests. Each class has its own log named according to the class’s fully qualified name. For example the class DefaultHttpClient has a log named org.apache.http.impl.client.DefaultHttpClient . Since all classes follow this convention it is possible to configure context logging for all classes using the single log named org.apache.http.impl.client .
Wire Logging
The wire log is used to log all data transmitted to and from servers when executing HTTP requests. The wire log uses the org.apache.http.wire logging category. This log should only be enabled to debug problems, as it will produce an extremely large amount of log data.
HTTP header Logging
Because the content of HTTP requests is usually less important for debugging than the HTTP headers, the org.apache.http.headers logging category for capturing HTTP headers only.
Configuration Examples
Commons Logging can delegate to a variety of loggers for processing the actual output. Below are configuration examples for Commons Logging , Log4j 2 and java.util.logging .
Commons Logging Examples
Commons Logging comes with a basic logger called SimpleLog . This logger writes all logged messages to System.err . The following examples show how to configure Commons Logging via system properties to use SimpleLog . It is strongly recommended configuring Commons Logging system properties through JVM process arguments at the start up.
- Enable header wire + context logging — «Best for Debugging»
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG -Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=ERROR
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.conn=DEBUG
-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog -Dorg.apache.commons.logging.simplelog.showdatetime=true -Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.conn=DEBUG -Dorg.apache.commons.logging.simplelog.log.org.apache.http.impl.client=DEBUG -Dorg.apache.commons.logging.simplelog.log.org.apache.http.client=DEBUG
Log4j 2 Examples
The simplest way to configure Log4j 2 is via a log4j2.xml file. Log4j 2 will automatically configure itself using a file named log4j2.xml when it’s present at the root of the application classpath.
Below are some Log4j configuration examples.
Note: The Log4j 2 implementation a.k.a “core” is not included in the HttpClient distribution. You can include it in your project using Maven, Ivy, Gradle, or SBT.
- Enable header wire + context logging — Best for Debugging
The Log4J 2 manual is the best reference for how to configure Log4J 2 . It is available at https://logging.apache.org/log4j/2.x/manual/.
java.util.logging Examples
Since JDK 1.4 there has been a package java.util.logging that provides a logging framework similar to Log4J . By default it reads a config file from $JAVA_HOME/jre/lib/logging.properties which looks like this (comments stripped):
handlers=java.util.logging.ConsoleHandler .level=INFO java.util.logging.FileHandler.pattern = %h/java%u.log java.util.logging.FileHandler.limit = 50000 java.util.logging.FileHandler.count = 1 java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter java.util.logging.ConsoleHandler.level = INFO java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter com.xyz.foo.level = SEVERE
To customize logging a custom logging.properties file should be created in the project directory. The location of this file must be passed to the JVM as a system property. This can be done on the command line like so:
$JAVA_HOME/java -Djava.util.logging.config.file=$HOME/myapp/logging.properties -classpath $HOME/myapp/target/classes com.myapp.Main
Alternatively LogManager#readConfiguration(InputStream) can be used to pass it the desired configuration.
- Enable header wire + context logging — Best for Debugging
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.level = FINEST org.apache.http.wire.level = SEVERE
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.level = FINEST
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.impl.conn.level = FINEST
.level = INFO handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.ConsoleHandler.level = ALL org.apache.http.impl.conn.level = FINEST org.apache.http.impl.client.level = FINEST org.apache.http.client.level = FINEST
More detailed information is available from the Java Logging documentation.
Logging Practices
Being a library HttpClient is not to dictate which logging framework the user has to use. Therefore HttpClient utilizes the logging facade provided by the Simple Logging Facade for Java (SLF4J) package. SLF4J provides a simple and generalized log interface to various logging packages. By using SLF4J , HttpClient can be configured for a variety of different logging behaviours. That means the user will have to make a choice which logging implementation to use. There are several popular logging backends that can be used through the SLF4J facade APIs:
HttpComponents project however mostly works with Log4j 2 backend and recommends it to our users.
HttpClient performs three different kinds of logging: the standard context logging used within each class, HTTP header logging and full wire logging.
Understanding Logger Names
Most logging implementations use a hierarchical scheme for matching logger names with logging configuration. In this scheme, the logger name hierarchy is represented by ‘ . ’ characters in the logger name, in a fashion very similar to the hierarchy used for Java package names. For example, org.apache.logging.appender and org.apache.logging.filter both have org.apache.logging as their parent. In most cases, applications name their loggers by passing the current class’s name to LogManager.getLogger(. ) .
Context Logging
Context logging contains information about the internal operation of HttpClient as it performs HTTP requests. Each class has its own logger named according to the class’s fully qualified name. For example the class DefaultHttpClient has a logger named org.apache.http.impl.client.DefaultHttpClient . Since all classes follow this convention it is possible to configure context logging for all classes using the single logger named org.apache.hc.client5.http .
Wire Logging
The wire logger is used to log all data transmitted to and from servers when executing HTTP requests. The wire logger uses the org.apache.hc.client5.http.wire logger name. This logger should only be enabled to debug problems, as it will produce an extremely large amount of log data.
HTTP header Logging
Because the content of HTTP requests is usually less important for debugging than the HTTP headers, use the org.apache.hc.client5.http.headers logger for capturing HTTP headers only.
Configuration Examples
SLF4J can delegate to a variety of logging implementations for processing the actual output. Below are configuration examples for Log4j 2 , Commons Logging , and java.util.logging .
Log4j 2 Examples
The simplest way to configure Log4j 2 is via a log4j2.xml file. Log4j 2 will automatically configure itself using a file named log4j2.xml when it’s present at the root of the application classpath.
Below are some Log4j configuration examples.
Note: The Log4j 2 implementation a.k.a “core” is not included in the HttpClient distribution. You can include it in your project using Maven, Ivy, Gradle, or SBT.
- Enable header wire + context logging — Best for Debugging