Partner – Microsoft – NPI (cat= Spring Boot)
announcement - icon

Azure Spring Apps is a fully managed service from Microsoft (built in collaboration with VMware), focused on building and deploying Spring Boot applications on Azure Cloud without worrying about Kubernetes.

And, the Enterprise plan comes with some interesting features, such as commercial Spring runtime support, a 99.95% SLA and some deep discounts (up to 47%) when you are ready for production.

>> Learn more and deploy your first Spring Boot app to Azure.

You can also ask questions and leave feedback on the Azure Spring Apps GitHub page.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

Logging is an important part of any software application, and it helps with troubleshooting and debugging issues. In addition, it can be used for monitoring purposes. Spring Boot supports popular logging frameworks, such as Logback and Log4j2. Spring Boot provides a couple of extensions to Logback and Log4j2 that may be useful for an advanced configuration.

In this tutorial, we’ll look into the Logback and Log4j2 extensions in a Spring Boot application.

2. Logback Extensions

Spring Boot uses the Logback library for logging by default. In this section, we’ll learn about a couple of extensions to Logback that can help with advanced configuration.

It’s also worth mentioning that Spring Boot recommends using logback-spring.xml for Logback instead of the default logback.xml. We cannot use extensions in standard logback.xml because the logback.xml configuration file is loaded too early.

2.1. Maven Dependencies

To use Logback, we need to add the logback-classic dependency to our pom.xml. However, the logback-classic dependency is already available in the Spring Boot Starter dependencies.

So, we need only to add the spring-boot-starter-web dependency to pom.xml:

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

2.2. Basic Logging

First, we’ll add some logs to the main Spring Boot class to use in our example:

@SpringBootApplication
public class SpringBootLogbackExtensionsApplication {

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

    public static void main(String[] args) {
        SpringApplication.run(SpringBootLogbackExtensionsApplication.class, args);

        logger.debug("Debug log message");
        logger.info("Info log message");
        logger.error("Error log message");
        logger.warn("Warn log message");
        logger.trace("Trace log message");
    }
}

2.3. Profile-Specific Settings

Spring profiles provide a mechanism for adjusting the application configuration based on the active profile.

For example, we can define separated Logback configurations for various environments, such as “development” and “production”. If we want to have a single Logback configuration, we can use the springProfile element in logback-spring.xml.

Using the springProfile element, we can optionally include or exclude sections of configuration based on the active Spring profiles. We can use the name attribute to allow which profile accepts the configuration.

By default, Spring Boot logs to the console only. Now, suppose we want to log things to a file for “production” and a console for “development”. We can easily do it by using the springProfile element.

Let’s create a logback-spring.xml file:

<springProfile name="development">
    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <root level="info">
        <appender-ref ref="Console" />
    </root>
</springProfile>

<springProfile name="production">
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/spring-boot-logger.log</file>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS}/archived/spring-boot-logger-%d{yyyy-MM-dd}.log</fileNamePattern>
        </rollingPolicy>
    </appender>
    <root level="info">
        <appender-ref ref="RollingFile" />
    </root>
</springProfile>

Then, we can set the active profile using the JVM system parameter -Dspring.profiles.active=development or -Dspring.profiles.active=production.

Now, if we run our Spring Boot application with the profile development, we’ll get the following output in the console:

10:31:13.766 [main] INFO  c.b.e.SpringBootLogbackExtensionsApplication - Info log message
10:31:13.766 [main] ERROR c.b.e.SpringBootLogbackExtensionsApplication - Error log message
10:31:13.766 [main] WARN  c.b.e.SpringBootLogbackExtensionsApplication - Warn log message

Also, we might want to log things to a file for “staging” or “production”. To support this case, the springProfile’s name attribute accepts a profile expression. A profile expression allows for more complicated profile logic:

<springProfile name="production | staging">
    <!-- configuration -->
</springProfile>

The above configuration is enabled when either the “production” or “staging” profile is active.

2.4. Environment Properties

Sometimes, we need to access values from the application.properties file in the logging configuration. In this situation, we use the springProperty element in the Logback configuration.

The springProperty element is similar to Logback’s standard property element. However, we can determine the source of the property from the environment rather than specifying a direct value.

The springProperty element has a source attribute, which takes the value of the application property. If a property isn’t set in the environment, it takes a default value from the defaultValue attribute. Also, we need to set a value to the name attribute to reference the property in other elements in the configuration.

Finally, we can set the scope attribute. A property in context scope is part of the context, and it’s available in all logging events.

Let’s suppose we want to use the application name as the log file’s name. First, we define the application name in the application.properties file:

spring.application.name=logback-extension

Then, we expose the application name for use within logback-spring.xml:

<property name="LOGS" value="./logs" />
<springProperty scope="context" name="application.name" source="spring.application.name" />
<springProfile name="production">
    <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS}/${application.name}.log</file>
        <!-- configuration -->
    </appender>
</springProfile>

In the above configuration, we set the source attribute of the springProperty element to the property spring.application.name. In addition, we refer to the property using ${application.name}.

In the next section, we’ll discuss Log4j2 extensions in a Spring Boot application.

3. Log4j2 Extensions

The Log4j2 Extensions are similar to the Logback Extensions. We cannot use extensions in the standard log4j2.xml configuration file because it’s loaded too early.

The recommended way in Spring Boot is to store the Log4j2 configuration in a separate file named log4j2-spring.xml. Spring Boot will load this before any other Log4j2 configuration if it exists.

3.1. Maven Dependencies

To use the Log4j2 library rather than the default Logback, we need to exclude Logback from our starter dependencies:

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

Also, we need to add spring-boot-starter-log4j2 and log4j-spring-boot dependencies to our pom.xml file:

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

We include the log4j-spring-boot library in our application for supporting the Spring Boot profile in the Log4j2 setting. When we don’t have this dependency, we’ll see the following error message:

2023-01-21 15:56:12,473 main ERROR Error processing element SpringProfile ([Loggers: null]): CLASS_NOT_FOUND

3.2. Profile-Specific Settings

Although putting the settings into different logging configurations would work in most situations, there might be cases where we’d like to have single logging settings for different environments. In that case, we can add a Spring Boot profile to our configuration using the SpringProfile element.

Let’s write a simple log4j2-spring.xml:

<SpringProfile name="development">
    <Logger name="com.baeldung.extensions" level="debug"></Logger>
</SpringProfile>

<SpringProfile name="production">
    <Logger name="com.baeldung.extensions" level="error"></Logger>
</SpringProfile>

This is similar to the example we discussed in the Logback section.

If we run the application with the production profile, we’ll now see the ERROR logs from our application, and there will be no more DEBUG logs from the com.baeldung.extensions package:

2023-01-22T11:19:52,885 ERROR [main] c.b.e.SpringBootLog4j2ExtensionsApplication: Error log message
2023-01-22T11:19:52,885 FATAL [main] c.b.e.SpringBootLog4j2ExtensionsApplication: Fatal log message

It’s important to note that SpringProfile sections are supported anywhere inside the configuration element.

3.3. Environment Properties Lookup

Log4j2 Lookups provide a way to provide values for our logging configuration file.

We can access values from the application.properties file using Log4j2 Lookup in our Log4j2 configuration. In addition, we can use the values of the active and default profiles. To do this, within our Log4j2 configuration, we can use spring-prefixed lookups.

Let’s set the spring.application.name=log4j2-extension in the application.properties file. Then, we read the spring.application.name from the Spring Environment:

<Console name="Console-Extensions" target="SYSTEM_OUT">
    <PatternLayout
        pattern="%d %p %c{1.} [%t] ${spring:spring.application.name} %m%n" />
</Console>

In the above configuration, we set the spring.application.name using the spring-prefixed lookups. After running, the application will log the following messages to the console:

2023-01-22 16:17:30,301 ERROR c.b.e.SpringBootLog4j2ExtensionsApplication [main] log4j2-extension Error log message
2023-01-22 16:17:30,301 FATAL c.b.e.SpringBootLog4j2ExtensionsApplication [main] log4j2-extension Fatal log message

3.4. Log4j2 System Properties

Log4j2 provides several System Properties that can be used to configure various aspects. We can add these system properties to log4j2.system.properties file.

Let’s add the log4j2.debug=true property. This system property prints all internal logging to the console:

TRACE StatusLogger Log4jLoggerFactory.getContext() found anchor class java.util.logging.Logger

Also, we can add system properties to the application.properties file. The property defined in the log4j2.system.properties file has a higher priority than the application.properties file.

4. Conclusion

Spring Boot comes with extensive logging support. In this tutorial, we’ve explored Logback and Log4j2 extensions in Spring Boot.

As always, the full source code of Logback extensions is available over on GitHub. Additionally, the Log4j2 extensions’ source code is also available over on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.