Logging in Spring Boot

What are logs ?

  • Logs in any project helps in understanding what all activities are going on with the application and to trace any unusual incident or error occurs in the project
  • It helps in debugging and analysing the application's bugs during runtime.
  • Application logging is very 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 Spring Framework, we have to configure the logging framework explicitly in our application. But Spring Boot provides support for several logging frameworks and also allows you to customize and tune logging in to your Spring application. Spring Boot includes, by default:

  • SLF4J: Logging facade
  • Logback: SLF4J implementation

Spring boot uses Logback for its default logging and because of this we do not need to provide any specific configuration to see the logs in the console.

Spring Boot also supports other logging frameworks such as Java Util Logging, Log4J, and Log4J2. You can use another logging frameworks by just adding a dependency.

Log Levels

Logging in Spring Boot comprises of different levels includes :

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL
  • OFF
  • null

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.

ERROR has a higher priority over other levels.

Lets understand each of the logging levels :

  • 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 aren'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.

Enabling Logs in Spring Boot

To enable logging in Spring boot, 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(LogController.class);
                                            

This log is usually defined at the very top of the global variable list, since it's a constant. 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:

Let's create a Spring Boot module. The recommended way to do so is using Spring Initializr, which we have covered it in our Spring Initializr Tutorial.

Now let's create our only class file, LoggingController.java:

                                            
    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 LoggingController {
                                
        private static final Logger logger = LoggerFactory.getLogger(LoggingController.class);

        @RequestMapping("/")
        public String index() {
            logger.trace("A TRACE Message");
            logger.debug("A DEBUG Message");
            logger.info("A INFO Message");
            logger.warn("A WARN Message");
            logger.error("A ERROR Message");
            
            return "Check out the Logs to see the output...";
        }
    }
                                        

Once the application is loaded, you will be able to see those logging lines by simply visiting http://localhost:8080/ or in the console. The console logs look like :

Fig : Log output

The following items are output in console:

  • 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.

Configuring Log Levels in application.properties file:

  • 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.

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
                                            

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.