Using Logback with Spring Boot

Using Logback with Spring Boot

26 Comments

In this post we will explore using Spring Boot’s default logging framework, Logback.

Logback makes an excellent logging framework for enterprise applications. It’s fast, and has simple but powerful configuration options, and comes with a small memory footprint. I introduced logback in my introductory post, Logback Introduction: An Enterprise Logging Framework.

In a series of posts on Logback, I’ve also discussed how to configure Logback using XML and Groovy. The posts are available as Logback Configuration: using XML and Logback Configuration: using Groovy.

In this post, I’ll discuss how to use Logback with Spring Boot. While there are a number of logging options for Java, the Spring Boot chose to use Logback for the default logger. Like many things in Spring Boot, Logback, by default, gets configured with sensible defaults.

Log Levels

Available Log Levels

Logback, and most Java logging frameworks has 5 log levels:

  • trace – Detailed, fine grained, messages from program execution
  • debug – Messages intended to help debug program execution
  • info – informational messages, often some type of event to record
  • warn – A warning message about an unusual condition
  • error – Message that an unexpected error occured.

Log Level Selection

When a log level is selected, the selected log level and all higher log levels will produce output.

  • trace enabled – trace, debug, info, warn and error produce log output.
  • debug enabled – debug, info, warn and error produce log output.
  • info enabled – info, warn and error produce log output.
  • warn enabled – warn and error produce log output.
  • error enabled – Only error produces log output.

Log Level Inheritance

The log level can be set at the root, package segment, and class level The log level will be inherited up this chain. If you set a log level for a package segment, the log level will apply to all classes under that segment.

For example, if we set the log level on the package guru.springframework.controllers to debug all classes in guru.springframework.controllers and classes in any sub-packages will have their log level set to debug.

Log Level Inheritance Examples

LoggerAssigned LevelInherited Level
rootinfoinfo
gurunoneinfo
guru.springframeworknoneinfo
guru.springframework.controllersnoneinfo
LoggerAssigned LevelInherited Level
rootwarnwarn
gurunonewarn
guru.springframeworkdebugdebug
guru.springframework.controllersnonedebug
LoggerAssigned LevelInherited Level
rooterrorerror
gurunoneerror
guru.springframeworkinfoinfo
guru.springframework.controllersnoneinfo
guru.springframework.controllers.IndexControllertracetrace

SLF4J – Simple Logging Facade for Java

SLF4J uses the Facade Design Pattern to provide an abstraction to popular Java logging frameworks.

Spring Boot uses SLF4J to allow for the easy configuration of alternate logging frameworks. Spring Boot starter artifacts include the SLF4J binding to Logback, and the Logback implementation.

When developing your Spring Boot Application, for logging, you will wish to use the SLFJ4 components, and NOT the logback components directly.

Should you ever wish to use a different logging implementation, you will be able to change without updating your application code.

Spring Boot Logback Example

Initial Setup

To follow this tutorial, you can create a new Spring Boot project using the Spring Initializr.

Add the following dependencies:

  • Spring MVC
  • Lombok

You can also find this project in my Github repository here.

Dependencies

We can examine the Maven dependency tree to see the dependencies the Spring Boot starter is adding to the project.

logback dependencies for Spring Boot

Here we can see the Spring Boot starter for Spring MVC (web) brings in the Spring Boot starter for logging. Under this dependency we can the the dependencies for Logback. Logback itself implements the binder for SLF4J, and includes the SLF4J API.

Creating Logback Loggers

Add the following Spring MVC controller to your Spring Boot project.

package guru.springframework.springlogback.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class IndexController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @RequestMapping(value = "/" )
    Map<String, String>  index(){
        logger.trace("This is a trace message");
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.warn("This is a warn message");
        logger.error("This is an error message");

        return Map.of("message", "Hello, World!");
    }
}

In this example, we get an SLF4J logger from the SLF4J logger factory with the class of the controller.

When the index() method is called, 5 logging statements, one for each log level, are called.

You can start your Spring Boot application and go to the url http:\\localhost:8080 in your browser. You’ll see the Hello World message in the browser. In the console, you will see the following output.

2024-10-17T14:16:35.487-04:00  INFO 76058 --- [spring-logback] [nio-8080-exec-2] g.s.s.controller.IndexController         : This is an info message
2024-10-17T14:16:35.487-04:00  WARN 76058 --- [spring-logback] [nio-8080-exec-2] g.s.s.controller.IndexController         : This is a warn message
2024-10-17T14:16:35.487-04:00 ERROR 76058 --- [spring-logback] [nio-8080-exec-2] g.s.s.controller.IndexController         : This is an error message

Notice, you are only seeing info, warn, and error log messages. The trace and debug messages are not there.

This is because the default configuration Spring Boot uses sets the root log level to info.

Creating Logback Loggers with Project Lombok

Project Lombok has become very popular for its features saving us from writing excessive cerimonial code. I previously covered Project Lombok in this post. In this post I wish to cover creating loggers using Project Lombok.

Project Lombok will generate code for you at compile time through a Java feature known as Annotation Processing. To use Project Lombok, be sure to add the dependency and enable Annotation processing in your IDE compiler settings.

Here is an example controller using Project Lombok to create its logger.

@Slf4j
@RestController
public class LombokController {
    
    @RequestMapping(value = "/lombok" )
    Map<String, String> index(){
        log.trace("This is a trace message");
        log.debug("This is a debug message");
        log.info("This is an info message");
        log.warn("This is a warn message");
        log.error("This is an error message");

        return Map.of("message", "Hello, World!");
    }
}

In the above example, we annotate the class with the Project Lombok annotation @Slf4j.

At compile time, Project Lombok will add the following to your class:

private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LombokController.class);

While it is a small time saver, its is easy to use. And in my opinion, your code is cleaner.

In this case, we are using the SLF4J logger. Project Lombok supports the popular Java logging frameworks.

Setting Log Levels

Setting Log Levels from the Command Line

We can pass --debug or --trace as command line arguments to change the log level of the root logger.

For finer control, we can change just the log level of our class using the following command line argument:

-Dlogging.level.guru.springframework.springlogback.controller=TRACE

If we are using the Spring Boot Maven Plugin to run the application, we can pass the following command line argument to change the log level.

mvn spring-boot:run 
  -Dspring-boot.run.arguments=--logging.level.guru.springframework.springlogback.controller=trace

If we are using the Spring Boot Gradle plugin, we can pass the following command line argument to change the log level.

./gradlew bootRun -Pargs=--logging.level.guru.springframework.springlogback.controller=TRACE

Setting Log Levels from Environment Variables

We can also control log levels by setting environment variables. For example, we could set:

export LOGGING_LEVEL_ROOT=ERROR
export LOGGING_LEVEL_GURU_SPRINGFRAMEWORK=TRACE

Setting Log Levels from application.properties

To change log levels from application.properties, we can add the following:

logging.level.root=error
logging.level.guru.springfamework=TRACE

Setting Log Levels in Logback XML Configuration

In the Logback XML Configuration file, we can set the following:

<logger name="guru.springframework" level="DEBUG" />

We’ll look closer at XML configuration later in this post.

Setting Log Levels Using Spring Boot Profiles

While developing in your local machine, it is common to set the log level to DEBUG. This will give you detailed log messages for your development use. While on production, it is typical to set the log level to WARN or above. This is to avoid filling your logs with excessive debug information and logging overhead while running in production. While logging is very efficient, there is still a cost.

There are two ways to set log levels using Spring Boot Profiles. Using appplication.properties and using the Logback configuration file.

To use application.properties with the profile name appended to “application”. For example, a properties file for the active profile dev would be application-dev.properties or application-dev.yaml.

Spring Boot has addressed these requirements by extending Spring profiles for Logback configuration with the <springProfile> element. Using this element in your logback-spring.xml file, you can optionally include or exclude sections of logging configuration based on the active Spring profile.

Note: Support for <springProfile> in Logback configuration is available from Spring Boot 1.3.0.M2 milestone onwards.

Here is an XML example to configure Logback using active Spring profiles.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <springProfile name="dev,staging">
        <logger name="guru.springframework.controllers" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE" />
        </logger>>
    </springProfile>
    <springProfile name="production">
        <logger name="guru.springframework.controllers" level="WARN" additivity="false">
            <appender-ref ref="FILE" />
        </logger>
    </springProfile>
 </configuration>

Log Level Configuration Hierarchy

If the log level is defined in multiple locations, the following hierarchy applies:

  • Log Levels set in application.properties will override XML properties
  • Log Levels set in application-<profile>.properties will override application.properties
  • Log Levels set in environment variables will override application.properties and application-<profile>.properties
  • Log Levels set via command line arguments will override environment variables

See Externalized Configuration for Spring Boot for additional information

Logback Configuration with Spring Boot

If you need more granular control over the Logback configuration, you can specify a configuration file.

If Spring Boot finds one of these 4 files on the classpath, it will load it over the default configuration.

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

Spring recommends using logback-spring.xml over logback.xml.

You can also include the Spring Boot default configuration an simply extend it with your customizations.

Following is an example logback-spring.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <include resource="org/springframework/boot/logging/logback/base.xml" />

    <logger name="guru.springframework" level="DEBUG"/>
</configuration>

In this example file, we are including the base Spring Boot Logback configuration, and setting the log level of the package guru.springframework to debug.

You can learn more about Logback XML configuration in this post, and Groovy configuration files.

Logback File Logging

By default, Spring Boot will only write log output to the console.

To enable log output to a file, you need to set the file name in the property logging.file.name or the directory to write log files to in the property logging.file.path.

NOTE: If you set both values, only logging.file.name is used.

The Spring Boot default configuration will rotate the log files when they reach 10 MB, and keep up to 7 archive log files. See the Spring Boot documentation if you would like to modify this behavior.

In the configuration code above, for the dev and staging profiles, we configured the guru.springframework.controllers logger to log DEBUG and higher level messages to console. For the production profile, we configured the same logger to log WARN and higher level messages to a file.

JSON Logging with Logback

For environments which need to use consolidated logging, it is common to use JSON log output. This is typically needed with distributed microservices.

If you need to setup JSON logging with Logback, check out this post!

Logback Auto-Scan Issue with Spring Boot

In a logback-spring.xml file, you can enable auto-scan of the configuration by setting the scan="true" attribute. With auto-scan enabled, Logback scans for changes in the configuration file. For any changes, Logback automatically reconfigure itself with them. You can specify a scanning period by passing a time period to the scanPeriod attribute, with a value specified in units of milliseconds, seconds, minutes or hours.
For example, this code tells Logback to scan logback-spring.xml after every 10 seconds.

<configuration debug="true" scan="true" scanPeriod="10 seconds" > 
  ...
</configuration>

One limitation of Spring Boot Logback is that with springProfile and springProperty, setting auto-scan results in error.

ANSI Color Mode

For console output, Logback will apply coloring to the console output. Refer to the Logback configuration guide if you would like to customize this.

ANSI Color Mode on Windows

To enable ANSI colors on Windows, you will need add the Jansi library version 1.17 or higher to your classpath and enable Jansi in the Logback configuration.

Add the following Maven dependency:

<dependency>
    <groupId>org.fusesource.jansi</groupId>
    <artifactId>jansi</artifactId>
    <version>2.4.1</version>
</dependency>

Following is a Logback configuration example to enable Jansi.

<configuration debug="true">
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <withJansi>true</withJansi>
    <encoder>
      <pattern>[%thread] %highlight(%-5level) %cyan(%logger{15}) -%kvp -%msg %n</pattern>
    </encoder>
  </appender>
  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

ANSI Color Mode on Linux and macOS

For Linux and macOS no additional configuration is required. These operating systems typically support ANSI colors natively. They do not need Jansi on the classpath, but doing so is harmless.

Following is an example of ANSI color console log output.

Logback with Spring Boot ANSI Color Console output

Use Log4J2 Instead of Logback with Spring Boot

For long time, the Java community considered Log4J the “best” logging framework. The team behind Log4J announced its end of life in 2015. Log4J is still used in a lot older, legacy applications.

Log4J4 is the successor of Log4J, and had its first GA release in 2014.

To use Log4J2 instead of Logback with Spring Boot, the steps are simple and straightforward. To use Log4J2, we need to:

  1. Exclude Logback from our dependencies
  2. Add the Log4J2 dependency
  3. Add the Log4J2 configuration

Since our application code is using SLF4J, rather than the logging framework directly, no further changes are required.

Log4J2 Dependencies

First we need to exclude the Log4J2 dependency from our Spring Boot starter was follows:

<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>

Next we need to add the Log4J2 Maven Dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

Log4J Configuration

The Spring Boot auto configuration will look for the Log4J2 configration in two files on the classpath:

  • log4j2-spring.xml
  • log4j2.xml

Following is an example log4j2-spring.xml configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Logger name="com.foo.Bar" level="trace" additivity="false">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

Conclusion

The popularity of Logback is trending in the open source community. A number of popular open source projects use Logback for their logging needs. Apache Camel, Gradle, and SonarQube are just a few examples.

Logback is clearly has the capabilities to handle the needs of logging in a complex enterprise application. So, it’s no wonder the Spring Boot team selected Logback for the default logging implementation. As you’ve seen in this post, the Spring Boot team has provided a nice integration with Logback. Out of the box, Logback is ready to use with Spring Boot. In this post, you’ve seen how easy it is to configure Logback in Spring Boot as your logging requirements evolve.

The source code used in this tutorial is available in my Github account here.

About jt

    You May Also Like

    26 comments on “Using Logback with Spring Boot

    1. June 8, 2016 at 9:23 am

      Great article, I liked the way we can change the logging level, by using application.properties file.

      Typo in:
      “will be sufficeint”

      Thanks,

      Richard Langlois P. Eng.
      Java Solutions Architect, Alithya, Montreal.

      Reply
    2. September 22, 2016 at 2:05 am

      Hi,

      can you please update that how to set the request id on each process logs ?

      In log4j, setting the request id in MDC works fine but not in slf4j.

      Reply
    3. November 18, 2016 at 5:16 am

      very helpful article, thank you

      Reply
    4. December 14, 2016 at 12:26 pm

      Is there any way to change the log file name programatically?

      Reply
    5. January 11, 2017 at 8:54 am

      Can you give an example with “scan=true” added. It would be just great. Because I am experiencing hard times with springProps and springProfile while live reload is unabled on configuration.

      Reply
    6. February 27, 2017 at 2:44 pm

      Could you please explain why logger property is not static ? with static field logger doesn’t work..

      private static final Logger logger = LoggerFactory.getLogger(MyClass.class.getClass())

      Reply
      • February 28, 2017 at 12:42 pm

        You can use

        private static final Logger logger = LoggerFactory.getLogger(MyClass.class);

        Reply
    7. March 24, 2017 at 10:20 am

      Thanks for making this point clear “However, you cannot specify both the logging.file and logging.path properties together. If done, Spring Boot will ignore both.” Got caught out by the Official Spring LoggingApplicationListener jav.doc which said the opposite : “By default, log output is only written to the console. If a log file is required the
      * {@code logging.path} and {@code logging.file} properties can be used.”.

      Made change to use anyone of the 2 enable logging for me!

      Reply
    8. April 10, 2017 at 6:24 am

      Really Great article …

      Reply
    9. April 24, 2017 at 2:57 pm

      Nice article to follow.

      Reply
    10. May 29, 2017 at 3:41 am

      Superb article.
      nicely explained. thumb zup for you 🙂

      Reply
    11. January 20, 2018 at 9:48 am

      As someone else pointed out. The right way to declare the logger is:

      `private static final Logger logger = LoggerFactory.getLogger(ClassName.class);`

      This way the logger can also be used from `static` methods not just instance ones. Furthermore, having the logger `static` ensures that it only gets instantiated once per class (rather than for every instance). Also any sub classes that also declare their own `logger` will get their own instance without doing nasty field hiding, which is a code smell in itself.

      Reply
    12. April 11, 2018 at 7:04 am

      “The Spring Boot team however recommends using the -spring variant for your logging configuration, logback-spring.xml is preferred over logback.xml” – why? Any specific reason?

      Reply
      • August 29, 2018 at 4:38 pm

        He explains that: “If you use the standard logback.xml configuration, Spring Boot may not be able to completely control log initialization.”

        Reply
    13. May 11, 2018 at 7:30 am

      Thank you for the great article !

      Reply
    14. May 12, 2018 at 8:24 pm

      does logback-spring.xml overrides application.properties or is it the other way round .

      Reply
    15. May 31, 2018 at 9:27 pm

      I prefer log4j2, just because it has the supplier parameter (lambda): logger.debug(“json: {}”, () -> json.toString())

      Reply
    16. June 15, 2018 at 9:39 pm

      Thanks. Well explained. Great article.

      Reply
    17. June 24, 2019 at 8:14 am

      I tried logging with application.properties, all the logging related properties and removed the log4j2.xml from resources, this works fine in local, but when i create the RPM of this and deploy on server , logs are not getting stored in file, while running service. if i run jar file over linux server everything works fine.
      Here i need log level to be changed from application.properties, if anyone have idea, plz reply

      Reply
    18. October 4, 2019 at 8:15 am

      Here is the code of the base.xml file from the spring-boot github repo.

      //404: Not Found

      🙁

      Reply
    19. February 9, 2022 at 11:27 am

      Property “logging.file” in application.properties File is not correct (anymore):

      Use “logging.file.name” instead of “logging.file”
      In higher versions of spring-boot-parent, property logging.file is deprecated.

      Reply

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.