Spring Boot 2 Logging SLF4j Logback and LOG4j2 Examples - RameshMF/spring-boot-developers-guide GitHub Wiki
In this article, we learn how to log effectively with Spring Boot. We will look at Spring Boot Starter for Logging. We will look at the defaults in Spring Boot for Logging - Logback, and SLF4J. We will also be looking at the Spring Boot starter for log4j2.
First, we will see how logging works in Spring Boot and then we will create a simple example to demonstrate the same.
Logging is a very important part of any application and it helps with debugging issues. Spring Boot, by default, includes spring-boot-starter-logging as a transitive dependency for the spring-boot-starter module. By default, Spring Boot includes SLF4J along with Logback implementations.
If Logback is available, Spring Boot will choose it as the logging handler. You can easily configure logging levels within the application.properties file without having to create logging provider-specific configuration files such as logback.xml or log4j.properties.
logging.level.org.springframework.web=INFO
logging.level.org.hibernate=ERROR
logging.level.net.guides=DEBUG
If you want to log the data into a file in addition to the console, specify the filename as follows
logging.path=/var/logs/app.log
or
logging.file=myapp.log
If you want to have more control over the logging configuration, create the logging provider-specific configuration files in their default locations, which Spring Boot will automatically use.
For example, if you place the logback.xml file in the root classpath, Spring Boot will automatically use it to configure the logging system
<configuration>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n </pattern>
</encoder>
</appender>
<logger name="com.apress" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
If you want to use other logging libraries, such as Log4J or Log4j2, instead of Logback, you can exclude spring-boot-starter-logging and include the respective logging starter, as follows:
<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-log4j</artifactId>
</dependency>
Now you can add the log4j.properties file to the root classpath, which Spring Boot will automatically use for logging.
The default log output from Spring Boot resembles the following example:
2014-03-05 10:57:51.112 INFO 45469 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
The following items are output:
- Date and Time: Millisecond precision and easily sortable.
- Log Level: ERROR, WARN, INFO, DEBUG, or TRACE.
- Process ID.
- A --- separator 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 configuration echoes messages to the console as they are written. By default, ERROR-level, WARN-level, and INFO-level messages are logged. You can also enable a “debug” mode by starting your application with a --debug flag.
$ java -jar myapp.jar --debug
You can also specify debug=true in your application.properties.
When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate, and Spring Boot) are configured to output more information. Enabling the debug mode does not configure your application to log all messages with DEBUG level.
By default, Spring Boot logs only to the console and does 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 (for example, in your application.properties).
So far we understood, how logging works in Spring Boot and default configurations. Now it's time to use Spring Boot 2 logging feature in our project so let's create an example to demonstrate how to use Spring Boot 2 logging feature.
Let's develop a simple in-memory Spring Boot 2 logging application.
There are many ways to create a Spring Boot application. The simplest way is to use Spring Initializr at http://start.spring.io/, which is an online Spring Boot application generator.
Look at the above diagram, we have specified following details:
- Generate: Maven Project
- Java Version: 1.8 (Default)
- Spring Boot:2.0.4
- Group: net.guides.springboot2
- Artifact: springboot2-logging
- Name: springboot2-logging
- Package Name : net.guides.springboot2.springboot2-logging
- Packaging: jar (This is the default value)
- Dependencies: Web Once, all the details are entered, click on Generate Project button will generate a spring boot project and downloads it. Next, Unzip the downloaded zip file and import it into your favorite IDE.
diagram here
Once we will import generated spring boot project in IDE, we will see some auto-generated files.
- pom.xml
- resources
- Springboot2LoggingApplication.java
- Springboot2LoggingApplicationTests.java
<?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>net.guides.springboot2</groupId>
<artifactId>springboot2-logging</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot2-logging</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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>
This class provides an entry point with the public static void main(String[] args) method, which you can run to start the application.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Springboot2LoggingApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot2LoggingApplication.class, args);
}
}
@SpringBootApplication is a convenience annotation that adds all of the following:
-
@Configuration tags the class as a source of bean definitions for the application context.
-
@EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings.
-
Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-web MVC on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
-
@ComponentScan tells Spring to look for other components, configurations, and services in the hello package, allowing it to find the controllers.
The main() method uses Spring Boot’s SpringApplication.run() method to launch an application. Did you notice that there wasn’t a single line of XML? No web.xml file either. This web application is 100% pure Java and you didn’t have to deal with configuring any plumbing or infrastructure.
package net.guides.springboot2.springboot2logging;
public class Article {
private int id;
private String name;
public Article(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package net.guides.springboot2.springboot2logging;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class ArticleService {
private static final Logger logger = LoggerFactory.getLogger(ArticleService.class);
public List<Article> getArticles(){
logger.debug("inside getArticles() method");
return Arrays.asList(new Article(100, "article"),new Article(200, "article2"));
}
}
Note that we have added slf4j Logger and also added debug statements.
private static final Logger logger = LoggerFactory.getLogger(ArticleService.class);
package net.guides.springboot2.springboot2logging;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ArticleController {
private static final Logger logger = LoggerFactory.getLogger(ArticleService.class);
@Autowired
private ArticleService articleService;
@GetMapping("/articles")
public List<Article> getArticles() {
logger.debug("inside ArticleController.getArticles() method");
return articleService.getArticles();
}
}
Note that we have added slf4j Logger and also added debug statements.
Let's configure logging properties in application.properties file. Open an application.properties file and add following logging configuration to it.
logging.level.org.springframework.web=INFO
logging.level.org.hibernate=ERROR
logging.level.net.guides=DEBUG
logging.file=myapp.log
Now run Springboot2WebappJspApplication.java as a Java application. Call REST API: http://localhost:8080/articles. You should see the list of articles in a JSON format.
[{"id":100,"name":"article"},{"id":200,"name":"article2"}]
Note that myapp.log file is created at your correct project location.
If you want to have more control over the logging configuration, create the logging provider specific configuration files in their default locations, which Spring Boot will automatically use.
For example, if you place the logback.xml file in the root classpath, Spring Boot will automatically use it to configure the logging system.
Let's create a logback.xml file in the root classpath(under resource folder), Spring Boot will automatically use it to configure the logging system.
<configuration>
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>app.log</file>
<encoder>
<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n </pattern>
</encoder>
</appender>
<logger name="com.apress" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
</configuration>
Re-run the application and app.log file is generated at your current location.