, ,

Using Logback with Spring Boot

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, IndexController to which we’ll add logging code. The code of IndexController is this.

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 :

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.

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.

Free Spring Framework Tutorial
Check out my FREE Introduction to Spring Course

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 to in addition to the console.

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

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

In the configuration code above, we included the base.xml file in Line 3, notice that we didn’t configured 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, its typical 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.

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

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.

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

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.

free spring framework tutorial
Checkout my FREE Introduction to Spring 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.

Share

You May Also Like

8 comments on “Using Logback with Spring Boot

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

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

  3. very helpful article, thank you

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

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

  6. 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())

    • You can use

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

Leave a Reply