Logging configuration in Spring Boot

Photo by Clay Banks on Unsplash

Problem

Spring Boot creates a default logging infrastructure with SLFJ as an abstraction layer over Logback. This works, but the default configuration logs with debug level and is overly verbose when using other libraries like JDBC and WebClient. We want to configure the log level with a configuration file to show the logs of our application and reduce library logs to errors or warnings.

Option 1: using Logback (recommended)

Since Logback is the logging framework that Spring Boot configures by default, this option is the simplest and should be preferred unless you have a reason to use a different logging system.

It’s worth noting that Spring Boot uses a Logback configuration that formats the logs in columns, which is not Logback’s default. It is desirable to keep this feature when we set up our own configuration, so our custom configuration is based on Spring’s (specifically the formatting part), with some tweaks for the level.

To configure Logback for use by the application and its unit tests, follow thes steps:

  • Create a file named logback.xml in src/main/resources with the following content:
<configuration>
    <!--
      The patterns used here are copied from Spring Boot's default Logback configuration which is available at
      https://github.com/spring-projects/spring-boot/blob/v2.4.0/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/logback/base.xml
    -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />

    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <property name="CONSOLE_LOG_CHARSET" value="${CONSOLE_LOG_CHARSET:-default}"/>
    <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>${CONSOLE_LOG_CHARSET}</charset>
        </encoder>
    </appender>
    <logger name="<base_package>" level="info"/>
    <root level="warn">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>
  • Replace <base_package> for the name of some package in your application that is high enough in the package hierarchy that all packages in your application are under it.
  • All loggers that aren’t created by our application code (such as those created by external libraries) will inherit the configuration of the root logger, which we have set to level warning in our configuration.
  • All the loggers created by our application code will inherit the configuration of the logger we have defined in the file above, tied to package <base_package>. This is why this package needed to be high in the package hierarchy.
  • That’s it. When you run the application and when your run tests, Logback will detect this file and use it. Note it’s not necessary to create a separate logback-test.xml file for unit tests. Maven automatically copies the logback.xml to the target folder and uses it when running tests, and it also includes it in the jar that the application runs from.

Option 2: using Log4J

  • To configure the log level of Log4J with a properties file, you need to use log4J 2.4 onwards. In a Spring Boot project, you will probably be using the spring-boot-starter as parent. This starter depends on spring-boot-starter-logging, which uses logback. So in order to use Log4J 2.4 we will need to exclude the dependency on spring-boot-starter-logging.
  • Use the following command to get your project’s dependency tree and find out which of your dependencies is bringing logback into the project:
mvn dependency:tree -Dverbose
  • Edit your pom, putting the following text inside that dependency:
<exclusions>
    <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-logging</artifactId>
    </exclusion>
</exclusions>
  • Add the following dependencies to your pom:
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.5</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.5</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-simple</artifactId>
    <version>1.7.30</version>
</dependency>
  • To configure the log level of unit tests, create a file src/test/resources/ in with the name log4j2-test.properties. This is the configuration file Log4J uses for tests.
    1. It is important to use this file name, otherwise Log4J will not use it.
  • Edit the configuration file with the following content. Note: this will loose Spring’s formatting of the log messages in columns.
status = error
name = PropertiesConfig
 
filters = threshold
 
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
 
appenders = console
 
appender.console.type = Console
appender.console.name = STDOUT
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %m%n
 
rootLogger.level = info
rootLogger.appenderRefs = stdout
rootLogger.appenderRef.stdout.ref = STDOUT

Sources

Leave a comment