A good logging infrastructure is necessary for any software project as it not only helps in understanding what’s going on with the application but also to trace any unusual incident or error present in the project. This article covers several ways in which logging can be enabled in a spring boot project through easy and simple configurations. Let’s first do the initial setup to explore each option in more depth.
Initial Setup
In order to create a simple Spring Boot project using Spring Initializer, please refer to this article. Let’s define a simple Rest Controller which outputs various levels of log messages.
Java
// Rest Controller to print various log level messages package com.log.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class LogController { // creating a logger Logger logger = LoggerFactory.getLogger(LogController. class ); @RequestMapping ( "/log" ) public String log() { // Logging various log level messages logger.trace( "Log level: TRACE" ); logger.info( "Log level: INFO" ); logger.debug( "Log level: DEBUG" ); logger.error( "Log level: ERROR" ); logger.warn( "Log level: WARN" ); return "Hey! You can check the output in the logs" ; } } |
Now we simply need to run the application and hit http://localhost:8080/log to see the log messages.
Default Logging With No Configurations
Spring boot allows us to see the logs in the console even if we do not provide any specific configuration for it. This is because spring boot uses Logback for its default logging. Spring boot’s internal logging provider is Apache Commons which provides support for Java Util Logging ,Log4j2, and Logback. Hence Apache Commons had to be manually imported until spring boot 1.x. However, since spring boot 2.x, it is downloaded transitively. To be more specific, Spring boot starters such as spring-boot-starter-web imports spring-boot-starter-logging which automatically pulls in Logback. On running the application and visiting the http://localhost:8080/log page, we can see the following output in the console:
The log format and ANSI colors are configured By Spring Boot beforehand to make the logging more readable. The following components are present in the log output:
- Date of logging
- Time with millisecond precision
- Log level shows INFO, WARN and ERROR by default
- Process ID
- — acts as a separator
- Name of the thread enclosed in square brackets
- Name of the logger that shows source class name
- The log message
Console Output
The log levels supported by Spring boot are TRACE,INFO,DEBUG,ERROR, and WARN. By default ERROR, INFO and WARN are printed to the console. It is possible to activate the debug and trace level by starting the application with –debug flag or –trace flag as follows:
java -jar target/log-0.0.1-SNAPSHOT.jar –debug
java -jar target/log-0.0.1-SNAPSHOT.jar –trace
Alternatively, This can also be done by adding the following properties in the application.properties file.
debug=true
trace=true
Color-Coded Output
If ANSI is supported by your terminal then color-coded log output can be seen in the console. The following property can be set in the application.properties file to get the color-coded output:
spring.output.ansi.enabled=always
Logging to a file
Spring boot only logs to the console by default. In order to log into a file, the following properties need to be added to the application.properties file:
logging.file.path=logs/
logging.file.name=logs/application.log
After adding these properties if we run the spring boot application and visit the page http://localhost:8080/log, we can see logs on the console as well as in the log file. A new folder by the name logs is created in the current path and inside this folder is the log file called application.log. The content of the log file is as follows:
Logging with Logback configuration
Spring boot enables logback to be configured in a specific manner to meet our project’s requirements. In order to do so, we need to define a configuration file where we can specify logging pattern, color, different properties for file logging & console logging, and an efficient rolling policy to prevent the creation of huge log files. Whenever Spring boot finds a file with any of the following names, It automatically overrides the default configuration.
- logback-spring.groovy
- logback.groovy
- logback-spring.xml
- logback.xml
Now let’s create a simple logback-spring.xml file
XML
<? xml version = "1.0" encoding = "UTF-8" ?> < configuration > <!-- Setting up log path and log file name --> < property name = "LOG_PATH" value = "./logs" /> < property name = "LOG_FILE_NAME" value = "application_logback" /> <!-- Setting up logging pattern for console logging --> < appender name = "ConsoleOutput" class = "ch.qos.logback.core.ConsoleAppender" > < layout class = "ch.qos.logback.classic.PatternLayout" > < Pattern > %white(%d{ISO8601}) %highlight(%-5level) [%yellow(%t)] : %msg%n%throwable </ Pattern > </ layout > </ appender > <!-- Setting the filename and logging pattern for log file --> < appender name = "LogFile" class = "ch.qos.logback.core.rolling.RollingFileAppender" > < file >${LOG_PATH}/${LOG_FILE_NAME}.log</ file > < encoder class = "ch.qos.logback.classic.encoder.PatternLayoutEncoder" > < Pattern >%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level : %msg%n </ Pattern > </ encoder > <!-- Setting up a rolling policy with rolling done daily and when file size is 10MB--> < rollingPolicy class = "ch.qos.logback.core.rolling.TimeBasedRollingPolicy" > < fileNamePattern >${LOG_PATH}/archived/${LOG_FILE_NAME}-%d{yyyy-MM-dd}.%i.log </ fileNamePattern > < timeBasedFileNamingAndTriggeringPolicy class = "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP" > < maxFileSize >10MB</ maxFileSize > </ timeBasedFileNamingAndTriggeringPolicy > </ rollingPolicy > </ appender > <!-- Logging at INFO level --> < root level = "info" > < appender-ref ref = "LogFile" /> < appender-ref ref = "ConsoleOutput" /> </ root > <!-- Logging at TRACE level --> < logger name = "com.log" level = "trace" additivity = "false" > < appender-ref ref = "LogFile" /> < appender-ref ref = "ConsoleOutput" /> </ logger > </ configuration > |
On running the application, and visiting the page http://localhost:8080/log, we receive the following console output:
The console output is as per the logging pattern and color defined in the logback-spring.xml file. A new log file by the name application-logback.log is created in the/logs folder present in the current path which gets archived through a rolling policy. The log file output is as follows:
Logging with Log4j2 configuration
For using log4j2, we need to exclude Logback from our starter dependency and add the dependency for log4j2 as follows:
XML
< 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 > |
Next, we need to define the configuration file for Log4j2. When spring boot finds a file with any of the following names, It automatically overrides it over default configuration.
- log4j2-spring.xml
- log4j2.xml
Now let’s create a simple log4j2-spring.xml file as follows:
XML
<? xml version = "1.0" encoding = "UTF-8" ?> < Configuration > <!-- Setting up log path and log file name --> < Properties > < property name = "LOG_PATH" value = "./logs" /> < property name = "LOG_FILE_NAME" value = "application-log4j2" /> </ Properties > <!-- Setting up logging pattern for console logging --> < Appenders > < Console name = "ConsoleOutput" target = "SYSTEM_OUT" > < PatternLayout pattern = "%style{%d{ISO8601}}{white} %highlight{%-5level} [%style{%t}{bright,yellow}] : %msg%n%throwable" disableAnsi = "false" /> </ Console > <!-- Setting the filename and logging pattern for log file. Also setting up a rolling policy with rolling done daily and when file size is 10MB --> < RollingFile name = "LogFile" fileName = "${LOG_PATH}/${LOG_FILE_NAME}.log" filePattern = "${LOG_PATH}/$${date:yyyy-MM}/application-log4j2-%d{dd-MMMM-yyyy}-%i.log.gz" > < PatternLayout > < pattern >%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level : %msg%n </ pattern > </ PatternLayout > < Policies > < OnStartupTriggeringPolicy /> < SizeBasedTriggeringPolicy size = "10 MB" /> < TimeBasedTriggeringPolicy /> </ Policies > </ RollingFile > </ Appenders > < Loggers > <!-- Logging at INFO level --> < Root level = "info" > < AppenderRef ref = "ConsoleOutput" /> < AppenderRef ref = "LogFile" /> </ Root > <!-- Logging at TRACE level --> < logger name = "com.log" level = "trace" additivity = "false" > < appender-ref ref = "LogFile" /> < appender-ref ref = "ConsoleOutput" /> </ logger > </ Loggers > </ Configuration > |
On running the application, and visiting the page http://localhost:8080/log, we receive the following console output:
The console output is as per the logging pattern and color defined in the logback-Log4j2.xml file. A new log file by the name application-Log4j2.log is created in the/logs folder present in the current path which gets archived through a rolling policy. The log file output is as follows: