Using Logback with Spring Boot

Using Logback with Spring Boot

26 Comments

Logback makes an excellent logging framework for enterprise applications. It’s fast, have 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. Out of the box, Spring Boot makes Logback easy to use.

Creating Loggers

In a previous post, I wrote about creating a web application using Spring Boot. We’ll configure Logback for this application. The application contains a controller called IndexController, to which we’ll add logging code. The code of IndexController is this.

   //package guru.springframework.controllers;


import guru.springframework.helpers.SpringLoggingHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @RequestMapping("/")
    String index(){
        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");
        new SpringLoggingHelper().helpMethod();
        return "index";
    }
}

Let’s add a SpringLoggingHelper class with logging code to the application. Although this class doesn’t do anything except emitting logging statements, it will help us understand configuring logging across different packages. Here is the code of SpringLoggingHelper :

   //package guru.springframework.helpers;


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

public class SpringLoggingHelper {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    public void helpMethod(){
        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");

    }
}

In both the classes above, we wrote logging code against the SLF4J API. SLF4J is a façade for commonly used logging frameworks, such as Java Util Logging, Log4J 2, and Logback. By writing against SLF4J, our code remains decoupled from Logback, thus providing us the flexibility to plug-in a different logging framework, if required later.

If you are wondering about SLF4J and Logback dependencies, you don’t need to specify any. Spring Boot contains them too. Assuming you’re using Maven or Gradle to manage you Spring Boot project, the necessary dependencies are part of the dependencies under Spring Boot.

Run the SpringBootWebApplication main class. When the application starts, access it from your browser with the URL, http://localhost:8080

The logging output on the IntelliJ console is this.

Logging Output with Default Configuration in Spring Boot

We haven’t written any configuration for Logback. The output of both the IndexController and SpringLoggingHelper classes are from the Logback root logger. Notice that the debug messages are not getting logged. Logback by default will log debug level messages. However, the Spring Boot team provides us a default configuration for Logback in the Spring Boot default Logback configuration file, base.xml.  In addition, Spring Boot provides provide two  preconfigured appenders through the console-appender.xml and file-appender.xml files. The base.xml file references both of them.

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

   //404: Not Found

Here you can see the Spring Boot has overridden the default logging level of Logback by setting the root logger to INFO, which is the reason we did not see the debug messages in the example above. As we’ll see in the next section, changing log levels in Spring Boot is very simple.

Spring Framework 5
Become an expert with Spring Framework 5!

Configuration via Spring Boot’s application.properties File

In a Spring Boot application, you can externalize configuration to work with the same application code in different environments. The application.properties file is likely the most popular of several different ways to externalize Spring Boot configuration properties. In the default structure of a Spring Boot web application, you can locate the application.properties file under the Resources folder. In the application.properties file, you can define log levels of Spring Boot, application loggers, Hibernate, Thymeleaf, and more. You can also define a log file to write log messages in addition to the console.

Here is an example of an application.properties file with logging configurations.

logging.level.org.springframework.web=INFO
logging.level.guru.springframework.controllers=DEBUG
logging.level.org.hibernate=ERROR
logging.file=logs/spring-boot-logging.log

Note: There is also a logging.path property to specify a path for a logging file. If you use it, Spring Boot creates a spring.log file in the specified path. However, you cannot specify both the logging.file and logging.path properties together. If done, Spring Boot will ignore both.

When you run the main class now and access the application, log messages from IndexController and SpringLoggingHelper are logged to the console and the logs/spring-boot-logging.log file.Spring Boot Logging Output with application.properties

In the output, notice that debug and higher level messages of IndexController got logged to the console and file. This is because in the application.properties file, we specified DEBUG as the log level for the guru.springframework.controllers package that IndexController is part of. Since we did not explicitly configure the SpringLoggingHelper class, the default configuration of base.xml file is used. Therefore, only INFO and higher level messages of SpringLoggingHelper got logged.

You can see how simple this is to use when you need to get more detailed log messages for a specific class or package.

Logback Configuration through an External File

Logback configuration through application.properties file will be sufficient for many Spring Boot applications. However, large enterprise applications are likely to have far more complex logging requirements. As I mentioned earlier, Logback supports advanced logging configurations through XML and Groovy configuration files.

In a Spring Boot application, you can specify a Logback XML configuration file as logback.xml or logback-spring.xml in the project classpath. The Spring Boot team however recommends using the -spring variant for your logging configuration,  logback-spring.xml is preferred over logback.xml. If you use the standard logback.xml configuration, Spring Boot may not be able to completely control log initialization.

Here is the code of the 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.controllers" level="WARN" additivity="false">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </logger>
    <logger name="guru.springframework.helpers" level="WARN" additivity="false">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </logger>
 </configuration>

In the configuration code above, we included the base.xml file in Line 3. Notice that we didn’t configure any appenders, rather we relied on the CONSOLE and FILE appenders which are provided by Spring Boot.

With the updated Spring Boot Logback configuration, our logging output now looks like this:

Logging Output of Spring Boot XML Configuration

Note: Spring Boot expects the logback-spring.xml configuration file to be on the classpath. However, you can store it in a different location and point to it using the logging.config property in application.properties.

Spring Boot Profiles in Logging

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.

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

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.

To pass a profile to the application, run the application with the -Dspring.profiles.active= JVM argument.

For local development, in IntelliJ, select Run-> Edit Configurations, and set the JVM argument in the Run/Debug Configurations dialog box, like this.

setting active profiles for logging in IntelliJ

Now, when we run the application with the dev profile, we will see the following log output.

Logging Output with Spring Active Profiles

In the output above, observe the logging output of IndexController. DEBUG and higher log messages got logged to console based on the configuration of the dev profile. You can restart the application with the production profile to ensure that WARN and higher log messages gets logged to the file.

Conditional Processing of Configuration File

Logback supports conditional processing of configuration files with the help of the Janino library. You can use <if>, <then> and <else> elements in a configuration file to target several environments. To perform conditional processing, add the Janino dependency to your Maven POM, like this.

. . .
<dependency>
   <groupId>org.codehaus.janino</groupId>
   <artifactId>janino</artifactId>
   <version>2.7.8</version>
</dependency>
. . .

The complete logback-spring.xml file with conditional processing logic is this.

   //

    
    
        
            
        >
    
    
    
        
    
    
    
        
            
                
            
        
        
            
                
            
        
    

In the code above, we specified a condition in the <if> element to check whether the current active profile contains dev. If the condition evaluates to true, the configuration code within the <then> element executes. In the <then> element, we configured guru.springframework.helpers to log DEBUG and higher messages to console. We used the <else> element to configure the logger to log WARN and higher messages to the log file. The <else> element executes for any profiles other than dev.

When you run the application with the production profile and access it, both loggers will log WARN and higher messages to the log file, similar to this.
Logging Output with production Profile

For the dev profile, both loggers will log DEBUG and higher messages to the console, similar to this.
Logging Output for dev Profile

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.

//Error on using auto-scan with springProfile

-ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:39 - no applicable action for [springProfile],   
 current ElementPath  is [[configuration][springProfile]]

//Error on using auto-scan with springProperty

 -ERROR in ch.qos.logback.core.joran.spi.Interpreter@12:125 - no applicable action for [springProperty],    
 current ElementPath  is [[configuration][springProperty]]

The error occurs because of incompatibility issues. Spring Boot uses the JoranConfigurator subclass to support springProfile and springProperty. Unfortunately, Logback’s ReconfigureOnChangeTask doesn’t provide a hook to plug it in.

Spring Framework 5
Become a Spring Framework Guru with my Spring Framework 5: Beginner to Guru course!

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.

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.