Spring Boot Logging

Introduction to Spring Boot Logging

Logging is one of the important features of any enterprise application, in this post we will get an understanding of Spring Boot Logging mechanism along with a few of configuration details.

 

Introduction 

Spring Boot comes with many ready-to-use features and Logging is one of those features, by default Spring Boot use Commons Logging for its internal logging but it also provides options to use and configure any other log mechanism. If we are using Spring Boot Starters for our application, it will use Logback for logging by default unless we want to use any other logging API like Log4J2

 

1.  Understand Log Output

Before we get into more details, let’s take a quick look at the default log out for the Spring Boot application to understand it more clearly.

2017-11-07 20:26:37.317  INFO 5388 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@53404716: startup date [Tue Nov 07 20:26:34 PST 2017]; root of context hierarchy
2017-11-07 20:26:37.404  INFO 5388 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/],methods=[GET || POST]}" onto public java.lang.String com.umesh.rest.web.controller.DemoController.sayHello(javax.servlet.http.HttpServletRequest) throws java.io.IOException
2017-11-07 20:26:37.407  INFO 5388 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/demo/greeting],methods=[GET]}" onto public java.lang.String com.umesh.rest.web.controller.LoggingDemoController.sayHello()
2017-11-07 20:26:37.409  INFO 5388 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2017-11-07 20:26:37.410  INFO 5388 --- [  restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)

There are certain things to understand above log output

  • Date and Time: First section shows date and time of the log output. (e.g. 2017-11-07 20:26:37.317)
  • Log Level: Second main output showed log level (e.g. INFO in our case).
  • Number as third output shows process id (e.g. 5388)
  • — showed separator
  • Output enclosed in [] shows Thread name.
  • Last 2 output shows Logger Name / Log Class name and logs message.

 

2.  Example

To understand how to configure and control Spring Boot Logging, let’s create a simple Controller with few log statements in it.

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

@Controller public class LoggingDemoController {
    
 private final Logger log = LoggerFactory.getLogger(this.getClass());
 
 @GetMapping("/demo/greeting") public String sayHello() {
  log.info("Info log statement for LoggingDemoController");
  log.warn("Warn log statement for LoggingDemoController");
  log.error("Error log statement for LoggingDemoController");
  return "greeting";
  
 }
}

On running above application by opening http://localhost:8080/demo/greeting, we can see following output in the console.

2017-11-07 20:43:41.566  INFO 5430 --- [io-10070-exec-4] c.u.r.w.c.LoggingDemoController          : Info log statement for LoggingDemoController
2017-11-07 20:43:41.567  WARN 5430 --- [io-10070-exec-4] c.u.r.w.c.LoggingDemoController          : Warn log statement for LoggingDemoController
2017-11-07 20:43:41.567 ERROR 5430 --- [io-10070-exec-4] c.u.r.w.c.LoggingDemoController          : Error log statement for LoggingDemoController

Spring Boot Logging API provides several features which help us to decouple our code

  • We are using SFL4J facade for our logging thus we are decoupled from the underlying Logback API.
  • By using it, we are free to replace Logback with any other logging API without changing our code base.

 

3.  Log File Output

by default, Spring Boot Logging API will log output to the console and not to any file, for writing log output to a file, we can set logging.file or logging.path property in the application.properties file.

logging.file =/work/demo/log/loggingdemocontroller.log
//or
logging.path= /work/demo/log

Please note that if in case we use logging.path property, Spring Boot will write a file with a name spring.log to the specified directory.

 

4.  Setting Log Levels

Spring Boot provides an easy way to configure and set logging levels for your application. We can use application.properties file to configure the desired Logging level for our application by using ‘logging.level.*=LEVEL’. Let’s use our previous example to get an understanding of setting log level in our application. We will configure our log level to output only WARN and ERROR logs.

application.properties

logging.level.com.javadevjournal.rest= WARN

On running above application by opening http://localhost:8080/demo/greeting, we can see following output in the console.

2017-11-08 20:05:13.362  WARN 8647 --- [nio-8080-exec-1] c.j.r.w.c.LoggingDemoController          : Warn log statement for LoggingDemoController
2017-11-08 20:05:13.362 ERROR 8647 --- [nio-8080-exec-1] c.j.r.w.c.LoggingDemoController          : Error log statement for LoggingDemoController

Since we configured our log level to the WARN, Spring Boot Logging API will only output log statements for WARN and higher (in our case WARN and ERROR).

We can configure the root logger using logging.level.root.Fore more detail, please read Spring Boot logging with application.properties

 

5.  Configure Logback Through External File.

For most of the applications, Spring Boot Logging default configurations are more than sufficient, however, for large-scale enterprise applications have complex logging requirements and Spring Boot provide a way to configure it through the external XML file.

You can put logback.xml or logback-spring.xml file in the root of your classpath it will be picked up from there by Spring Boot. Please note that logback-spring.xml is preferred over the logback.xml file by Spring Boot.

here is a sample logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
    <logger name="com.javadevjournal.rest" level="WARN" additivity="false">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </logger>
</configuration>

If you want to get more understanding of the System properties which the LoggingSystem takes care of creating for us, please have a look at base.xml file inside spring-boot jar and especially the following line 

<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}"/>

 

6. Spring Boot Profiles in Logging

Spring Profiling is an excellent concept which provides us the flexibility to define properties for the different environment with no code change. Spring Boot provides the same profile mechanism for the logback configuration by using the <springProfile> element. Let’s use an example to understand how you can define different logging level for DEV and Production environments using the same logback configuration.

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

Read Spring Profiles to get an understanding of how to use Spring Profiles feature for your application. 

 

7. Configure Log4j

Not all application wants to use default logging configuration, and it holds true for default logging mechanism, however, Spring Boot provides an easy way to use any other logging framework. In case you want to use Log4j2 for logging configuration, all you have to add the log4j2 starter in your application (no other complex configurations).

Please know if If you are using the starters for your application, you need to exclude logback and then include log4j 2 instead.Here is a sample configuration to use log4j for your application.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</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>

For more details on Log4J2, please read Log4j2 with Spring Boot

Summary 

In this post, we explored different features of the Spring Boot Logging API. We discussed what are the default configurations provided by Spring Boot along with options to configure or customize these options. Logging is one of the main tool in the application development and with complex enterprise applications, logging requirement can become complex with the time, however, Spring Boot API provides all the tools to handle all these complex use cases with minimal configuration changes.

If you are starting with Spring Boot, please read building an application with Spring Boot to start your journey with Spring Boot