Spring Boot Logging

Spring Boot Logging

In this article, We will learn about  Spring Boot Logging feature.

If you have not read my introduction article of Spring Boot, I would request you to take a look –  Spring Boot Tutorial.

Spring Boot is very easy to use framework and it has a lot of features. Logging in Spring Boot is very easily configurable and very flexible.

With very simple configurations, Spring Boot provides support for various Logging providers.

In this article, we will take a look at various logging configurations and options supported by Spring boot.

Let’s get started :

Default Zero Configuration Logging

spring-boot-starter-logging artifact/dependency determines the Spring Boot active enabled logging.
As Spring Boot has feature of Auto Configuration, It becomes very easy to use any supported Logging providers, as we can enable it by adding configurations.

Some Logging Providers are mentioned below :

  • Java Util
  • Logging
  • Log4J2
  • Logback

Spring Boot does provide the default logging feature. So even if we do not provide any configuration for the logging then also we will be able to see the logs in the console.

Default Logging in Spring Boot uses the Logback provider.

The internal logging of Spring boot is written with Apache Commons Logging and it is the one and only mandatory dependency.

This dependency was required to be downloaded manually till the Spring Boot version 1.x but since 2.x, this dependency is automatically downloaded transitively.

When I say transitivity, I mean spring-boot-starter-web depends on spring-boot-starter-logging dependency and it pulls in spring-jcl for us.

Spring boot auto-configuration feature provides us the default logging using Logback provider.

Addition of log statements

In Spring Boot, we need to use below mentioned libraries to add the log statements in our application code :

  • org.slf4j.Logger
  • org.slf4j.LoggerFactory .

These libraries are available in SLF4J.

These libraries provides lots of useful methods for logging .

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MainApp
{
private static final Logger LOGGER = LoggerFactory.getLogger(MainApp.class);

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

LOGGER.info("Testing Logging in console");
}
}

Output in Console : 

2019-09-26 11:12:23.154 INFO 3421 --- [main]
com.techblogstation.examples.MainApp: Testing Logging in console

Logging Levels

Logback supports various options or we can say levels of Logging :

  1. ERROR
  2. WARN
  3. DEBUG
  4. INFO
  5. TRACE

If we do not set any level then default level is set as INFO, which means that DEBUG and TRACE messages are not visible.

We need to set the level of Logging as per our requirement in the application.properties file of our Spring Boot Application.

Additionally, we can pass the arguments as -debug or -trace in order to enable these Logging levels

In the application.properties file, below code is needed :

debug=true

If enabling through Command line, then below command needs to be executed :

$ java -jar target/my-application-0.0.1-SNAPSHOT.jar --trace

Logging level can also be set as different for different packages. We can set it in either application.properties file or through cmd.

In application.properties :

logging.level.org.springframework=ERROR logging.level.com.techblogstation=TRACE

In console :

-Dlogging.level.org.springframework=ERROR -Dlogging.level.com.techblogstation=TRACE

Suppose If the log level for a package is defined multiple times with different log levels.

In this case , the lowest level will be used for the package.

TRACE is lowest and ERROR is highest.

Log Format

In Spring, The default log statement formatting is mentioned in defaults.xml file.

defaults.xml of Spring : 

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

<!--
Default logback configuration provided for import
-->

<included>
<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="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>

<logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/>
<logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/>
<logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/>
<logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/>
<logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/>
<logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/>
<logger name="org.hibernate.validator.internal.util.Version" level="WARN"/>
</included>

This defaults.xml outputs the logs in below format (consider the same order as below list has) :

  1. Date and Time
  2. Log Level: the levels of Logs : ERRORWARNINFODEBUG, or TRACE.
  3. Process ID.
  4. A  separator --- to be pasted in the start of each log message.
  5. Thread name:  It is enclosed in the square brackets (Sometimes trimmed).
  6. Logger name: It is usually the name of source class.
  7. The actual log message.

We can customize the log format for our Spring Boot Application using logging.pattern.console and logging.pattern.file properties.

application.properties
# Logging pattern for the console logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n # Logging pattern for file logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%

Logging to file

Spring Boot print logs in console by default but we can enable the logging for file as well.

A simple property logging.file or logging.path is used to enabling of Logging to file.

If we are using logging.path property then it will automatically create the spring.log file in the specified package.

application.properties
# Logging to a temp folder
logging.file=c:/temp/application.log

#logging.path=/my-techblog/

# Pattern for file Logging
logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%

Logback Logging

For most of the Spring Boot application, default Logging is considered as good but when we are dealing with large projects or applications then we might require more control over Logging.

So Our application requires that it has a dedicated Logging configuration.

As we already know, Spring Boot uses the Logback so we can customize its behavior by :

  • Adding logback.xml in classpath
  • Define the customization over the file
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

<property name="LOG_LOCATION" value="c:/temp" />

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<File>{LOG_LOCATION}/mylog.log</File>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} - %logger{36} - %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_LOCATION}/archived/mylog-%d{yyyy-MM-dd}.%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
</appender>

<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>

<!-- Properties for Application logs -->
<logger name="com.techblogstation" level="trace" additivity="false">
<appender-ref ref="RollingFile" />
<appender-ref ref="Console" />
</logger>

</configuration>

Log4j2 Logging

To be able to use the Logging of Log4j2 provider, below steps are required :

Exclude the logback and include log4j2

As we are aware that Spring Boot uses logback as its default Logging provider so In order to use another Logging provider or framework, we need to exclude the logback provider from our Spring Boot Application.

  1. Exclude the logback from the classpath of Application.
  2. Include the spring-boot-starter-log4j2 in classpath of Application.
<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>

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

Addition of log4j2 configuration file

Now, we are required to add log4j2 specific configuration file in our application’s classpath. This should typically reside in the resources folder.

We can name the file as any of the following:

  • log4j2.xml
  • log4j2-spring.xml

If we have named the file as something else then we can define the name of the file in logging.file property in our application.properties file.

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
    <Properties>
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd'T'HH:mm:ss.SSSZ} %p %m%n</Property>
        <Property name="APP_LOG_ROOT">c:/temp</Property>
    </Properties>
    <Appenders>
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="${LOG_PATTERN}" />
        </Console>
  
        <RollingFile name="file"
            fileName="${APP_LOG_ROOT}/SpringBoot2App/application.log"
            filePattern="${APP_LOG_ROOT}/SpringBoot2App/application-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout pattern="${LOG_PATTERN}" />
            <Policies>
                <SizeBasedTriggeringPolicy size="19500KB" />
            </Policies>
            <DefaultRolloverStrategy max="1" />
        </RollingFile>
  
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="console" />
            <AppenderRef ref="file" />
        </Root>
    </Loggers>
</Configuration>

With or without Slf4j

It is recommended that your application uses SLF4J logger classes.

If you are using SLF4J logger classes which are org.slf4j.Logger and org.slf4j.LoggerFactory then there is no requirement to change anything in the application code and all log statements will continue printing.

But, If you are targeting to use only the log4j2 specific classes then org.apache.logging.log4j.Logger and org.apache.logging.log4j.LogManageris used.

See below :

SLF4J logger classes
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@SpringBootApplication
public class MainApp
{
private static final Logger LOGGER = LoggerFactory.getLogger(MainApp.class);

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

LOGGER.info("Simple logging");
}
}
LOG4J2 logger classes

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@SpringBootApplication
public class MainApp
{
private static Logger LOGGER = LogManager.getLogger(MainApp.class);

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

LOGGER.info("Simple logging...");
}
}

Conclusion

That’s all folks! In this article,  we have learnt all about the Logging in Spring Boot, Different Logging Providers for Spring Boot and How to Configure different Logging providers, levels and many other options.

Leave a Reply

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