Introduction
Server logs are an important part of development that record the activities or events that the system is performing at any given point in time.
Spring Boot makes use of Apache Commons' Logging for its system logs by default. Additionally, by default you can use any of the logging frameworks under the SLF4J API such as Logback (which is the default), Log4J2, and Java Util Logging in Spring Boot.
Application logging is a powerful development tool that is important for production-level support and debugging. Each log entry contains information such as the timestamp, the actual method being called, a custom log message, and other contextual information. Each log entry also includes an identifier called a logging level.
In this tutorial, we'll take a look at how to perform Logging in Spring Boot, using SLF4J, as well as log levels and the configuration required to customize them, and log groups.
Log Messages in Spring Boot
To enable logging in Spring, import Logger
and LoggerFactory
from the org.slf4j
API library:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Afterwards, declare a constant to store the logger service by instantiating a logger for the class using LoggerFactory
:
private static final Logger log = LoggerFactory.getLogger(DemoService.class);
This log
is usually defined at the very top of the global variable list, since it's a constant. By providing the class you want to log, it's fully set up and ready to be called with the provided messages.
Alternatively, you can just annotate the class with @Slf4j
which will automatically generate a logger for the class without having to declare a constant. The annotation supplies a static variable called log
which provides the logger utilities by default:
@Slf4j
@Service
public class DemoService {
//...
}
Note: The most common identifier for the logger is log
, though you'll also see logger
in a lot of cases. Really, you're free to call it whatever you'd like, but log
is succinct and saves you from writing a longer name due to frequent calls.
Logging in Spring Boot comprises a few different levels. Every log has a degree of urgency or importance that is associated with a log level. Log levels are configured at runtime and each log request checks the log level to see if the request has equal or higher priority than the log level to be displayed.
If you try logging a message which is considered less important than some threshold, it just won't be logged.
Take this block for example, with messages of log importance in descending order:
public void logLevelDisplay () {
logger.error("Error message");
logger.warn("Warning message");
logger.info("Info message");
logger.debug("Debug message");
logger.trace("Trace message");
}
If no configurations are set in application.properties
or elsewhere, the log level will default to INFO
. So if we were to call the method logLevelDisplay()
, it would output something like this:
2020-12-20 12:46:35.880 ERROR 47958 --- [nio-8080-exec-1] c.service.DemoService : Error message
2020-12-20 12:46:52.976 WARN 47958 --- [nio-8080-exec-1 c.service.DemoService : Warn message
2020-12-20 12:46:59.104 INFO 47958 --- [nio-8080-exec-1] c.service.DemoService : Info message
The DEBUG
and TRACE
messages weren't displayed because the application's log level is set to INFO
, which has a higher priority level than the two.
If the log level was set to ERROR
, then only the error message would be displayed since it's the highest log level of the 5 built-in levels.
This brings us to an important topic - log levels, which deserve an explanation of their own.
Log Levels in Spring Boot
As mentioned before, logging in Spring Boot comprises different levels. For example, Hibernate SQL queries are categorized as DEBUG
, which is a low-urgency log level that is mainly invoked for debugging purposes.
Logging levels allows distinction between the following sample logs:
- Successfully updated
User
information: Updated nameJohn
toJon
. - NullPointerException:
id
ofUser
isnull
The first log is a general informative type of message while the second log is a NullPointerException
message.
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
These logs have different levels of urgency, and distinction between them using log levels is important for filtering out logs that don't have to be output depending on the circumstance. If there's a huge error going on, you don't want it to be cluttered by a bunch of working, low-level INFO
logs!
SLF4J provides 5 default logging levels in Spring boot:
ERROR
- Error logs are serious issues that affect a significant part of the system or some part of your application has failed to operate. Exceptions are considered ERROR
level logs. Other examples of error logs are database connection failures and configuration errors. ERROR
logs are the most urgent default log level in SLF4J.
WARN
- Warning logs are used to indicate potential problems that might cause errors and should be monitored in case they fail. Of course, the context of a warning is subjective to the developer and the situation so warning logs might vary from system to system.
INFO
-INFO
is the default logging level that is set by Spring Boot. If no configurations are made, the log level is automatically set to INFO
. These types of logs are information that isn't normally needed but is useful in situations like production code debugging or determining when certain data is manipulated.
DEBUG
- DEBUG
logs include more detailed, specific information that isn't needed in normal situations. This is often set as a log level when a developer is trying to deep trace a problem or a bug that is hard to trace.
TRACE
- TRACE
is a more granular version of DEBUG
. TRACE
logs are exhaustive, imagine logging every single operation the system is doing, from starting a service, initializing new variables, and calling methods.
In order of urgency, ERROR
is the most urgent while TRACE
is the least urgent log. The default log level in Spring Boot is INFO
when no manual configuration is set.
Configuring Log Levels in Spring Boot
Log levels can be set in the Spring environment by setting its configurations in application.properties
.
The format to set the log level configuration is logging.level.[classpath] = [level]
. The classpath is specified since different components of the application can be configured with different log levels, which is especially useful for code isolation and debugging.
To specify a log level for all classes that don't have their own log level settings, the root
logger can be set using logging.level.root
.
In application.properties
:
logging.level.root=INFO
logging.level.com.test=DEBUG
logging.level.com.service.DemoService=WARN
From this configuration, every class except DemoService
and the classes under the com.test
classpath will have their log levels set to INFO
, while the test
classes and DemoService
have their own specified log levels.
Log Groups
Log groups is a useful way to set logger configurations to a group of classes with different classpaths. An example is if you want to set all the test class log levels to DEBUG
in one go. This is possible using the configuration logging.group.[groupName]
:
# Initialize log group
logging.group.test=com.test, com.test-prod, com.apptest
# Set log level to log group
logging.level.test=DEBUG
With this approach, you won't have to individually set the log level of all related components all the time.
Conclusion
Knowing about the different log levels is important especially in situations like debugging in production.
Let's say a major bug has been exposed in production, and the current logs do not have enough information to diagnose the root cause of the problem. By changing the log level to DEBUG
or TRACE
, the logs will show much-needed information to pinpoint crucial details that may lead towards the fix.
In Spring, the log level configurations can be set in the application.properties
file which is processed during runtime. Spring supports 5 default log levels, ERROR
, WARN
, INFO
, DEBUG
, and TRACE
, with INFO
being the default log level configuration.