Logging Configuration in Spring Boot

Hello friends!!! Once again we are going to discuss very important topic about spring boot configuration. We always curious about defining tacking or logs basis things own way. Like Pizza organization provide the tracking about the ordered pizza what is the current status of pizza. Still we supposed to see more detailed status like information about pizza base or how to make pizza and also supposed there no problem happens in preparing the pizza.
 
Logging is not the core requirement for any business application but we cannot ignore it because logging is very important part for any application for tracking information about application and helpful for developer in debugging the application. In some applications developers use synchronous logging which can impact the application’s performance. Logging libraries like Logback, Log4j2 provide async logging.
Spring Boot provides support for logging and uses Commons Logging for all internal logging, but leaves the underlying log implementation open. Default configurations are provided for Java Util Logging, Log4J2 and Logback. In each case loggers are pre-configured to use console output with optional file output also available.
By default, if you use the ‘Starters’, Logback will be used for logging. Here we are going to use default logging by Spring Boot.

Default Logging Format in Spring Boot

The default logs look like as below
2016-07-24 20:31:45.280  INFO 10220 --- [           main] c.d.SpringBootHelloWorldApplication      : Starting SpringBootHelloWorldApplication on NODTBSL206AG with PID 10220 (started by Dinesh.Rajput in D:personal dataspring-boot-workspaceSpringBootHelloWorld)
2016-07-24 20:31:45.286  INFO 10220 --- [           main] c.d.SpringBootHelloWorldApplication      : No active profile set, falling back to default profiles: default
2016-07-24 20:31:45.502  INFO 10220 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1809907: startup date [Sun Jul 24 20:31:45 IST 2016]; root of context hierarchy
2016-07-24 20:31:48.201  INFO 10220 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
2016-07-24 20:31:48.226  INFO 10220 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2016-07-24 20:31:48.228  INFO 10220 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.3
2016-07-24 20:31:48.485  INFO 10220 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2016-07-24 20:31:48.485  INFO 10220 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2993 ms
The following items are output:

 

  • Date and Time: Millisecond precision and easily sort able.
  • Log Level: ERROR, WARN, INFO, DEBUG or TRACE.
  • Process ID.
  • ASeparator to distinguish the start of actual log messages.
  • Thread name: Enclosed in square brackets (may be truncated for console output).
  • Logger name: This is usually the source class name (often abbreviated).
The log message.
The default log level configured by logback is DEBUG i.e any messages logged at ERROR, WARN, INFO and DEBUG get printed on the console.

Create Spring Boot Maven Project

Let’s create a Maven Spring Boot project for customizing logging configuration.
POM.XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>

 <groupId>com.dineshonjava</groupId>
 <artifactId>SpringBootHelloWorld</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>SpringBootHelloWorld</name>
 <description>SpringBootHelloWorld project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.4.0.RC1</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <java.version>1.8</java.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>
 
 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>
</project>
In above pom.xml we do not need to add the logging dependency explicitly because dependency spring-boot-starter includes the dependencies for logging spring-boot-starter-logging. The spring-boot-starter-logging includes SLF4J and logback dependencies with appropriate SLF4J wrappers for other logging libraries.
Now let’s see Class file where we have logs message
package com.dineshonjava;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class SpringBootHelloWorldApplication {
 
private static final Logger logger = LoggerFactory.getLogger(SpringBootHelloWorldApplication.class);
 

@RequestMapping("/")
    String home() {
        return "Hello World!";
    }
 
public static void main(String[] args) {
    SpringApplication.run(SpringBootHelloWorldApplication.class, args);
    logger.error("Message logged at ERROR level");
    logger.warn("Message logged at WARN level");
    logger.info("Message logged at INFO level");
    logger.debug("Message logged at DEBUG level");
}
}

There are following logs look like after running above class.
2016-07-24 20:57:40.828 ERROR 3024 --- [           main] c.d.SpringBootHelloWorldApplication      : Message logged at ERROR level
2016-07-24 20:57:40.828  WARN 3024 --- [           main] c.d.SpringBootHelloWorldApplication      : Message logged at WARN level
2016-07-24 20:57:40.828  INFO 3024 --- [           main] c.d.SpringBootHelloWorldApplication      : Message logged at INFO level

Customizing default Configuration for Logging:

By adding logback.xml file to the application we can override the default logging configuration providing by the Spring Boot. This file place in the classpath (src/main/resources) of the application for Spring Boot to pick the custom configuration.
Logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- Log message format -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
      </pattern>
    </encoder>
  </appender>

  <!-- Setting the root level of logging to INFO -->
  <root level="info">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>
There are following things we have note:

 

  • We are using a appender STDOUT using ConsoleAppender which prints to the console
  • We are giving pattern to the appender to build the log message
  • Set up a root logger which logs any message above INFO level using the STDOUT appender
Spring-boot-logging
There are following logs look like after running this application.
21:14:46.352 [main] ERROR c.d.SpringBootHelloWorldApplication - Message logged at ERROR level
21:14:46.352 [main] WARN  c.d.SpringBootHelloWorldApplication - Message logged at WARN level
21:14:46.352 [main] INFO  c.d.SpringBootHelloWorldApplication - Message logged at INFO level
We have to note here in above logs there is no DEBUG logs printed.

Printing Logs into a File:

By default, Spring Boot will only log to the console and will not write log files. If you want to write log files in addition to the console output you need to set a logging.file or logging.path property in your application.properties.
There are following cases for logging property:

 

  • If No logging.path and No logging.file then Console only logging.
  • If No logging.path and Specify logging.file then writes to the specified log file. Names can be an exact location or relative to the current directory.
  • If Specify logging.path and No logging.file then writes spring.log to the specified directory. Names can be an exact location or relative to the current directory.
Log files will rotate when they reach 10 Mb and as with console output, ERROR, WARN and INFO level messages are logged by default.
Now let’s see the following changes we are made in the logback.xml as below
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- Log message format -->
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <!-- Need appender to write to file -->
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <!-- Name of the file where the log messages are written -->
    <file>MySpringBootApp.log</file>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <logger name="com.dineshonjava.service" level="warn">
    <appender-ref ref="FILE" />
  </logger>

  <!-- Setting the root level of logging to INFO -->
  <root level="info">
    <appender-ref ref="FILE" />
  </root>
</configuration>
Here we are introducing one more file “HelloService.java” for logging purpose as below:
package com.dineshonjava.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloService {
private Logger logger = LoggerFactory.getLogger(HelloService.class);
public void service(){
  logger.info("Message at INFO level from HelloService.service()");
  logger.warn("Message at WARN level from HelloService.service()");
}
}
Now running the application will redirect all the log messages to the file MySpringBootApp.log present in the current directory.
Spring-boot-logging-2

Custom log configuration

The various logging systems can be activated by including the appropriate libraries on the classpath, and further customized by providing a suitable configuration file in the root of the classpath, or in a location specified by the Spring Environment property logging.config.
Depending on your logging system, the following files will be loaded:
  1. Logback -> logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
  2. Log4j2 -> log4j2-spring.xml or log4j2.xml
  3. JDK (Java Util Logging) -> logging.properties

 

There are following properties we can use for custom log configuration
  1. logging.file -> Used in default log configuration if defined for logging file name.
  2. logging.path -> Used in default log configuration if defined for logging file path of directory.
  3. logging.pattern.console -> The log pattern to use on the console.
  4. logging.pattern.file -> The log pattern to use in a file.
  5. logging.pattern.level -> The format to use to render the log level.
  6. logging.exception-conversion-word -> The conversion word that’s used when logging exceptions.

 

Summary

Here we have seen enough things about how to use the logging processes in Spring Boot application. First we have see about the default logging support in the Spring Boot applications and then we have made it how to override them by modifying the logback.xml file. And also we have discussed list of all properties those we have used to customize the logging configuration in the spring boot application.

 

Happy Spring Boot Learning!!!

 

Previous
Next