Logging is an essential part of any application as it provides insight into the internal operations and helps track down issues. Spring Boot, a powerful framework for building Java applications, comes with an excellent logging system by default. However, sometimes developers need to tweak the logging configuration to suit the application’s needs. This article will explore how to configure logging in Spring Boot, test log severity, and adjust log levels dynamically using the LoggingSystem class, along with practical examples.

Introduction to Spring Boot Logging

Spring Boot uses the SLF4J (Simple Logging Facade for Java) as an abstraction layer and supports several logging frameworks, such as Logback, Log4J2, and Java Util Logging. By default, Spring Boot uses Logback as its default logging implementation, but it also provides the flexibility to switch to other frameworks.

Out of the box, Spring Boot provides basic logging capabilities with different log levels like ERROR, WARN, INFO, DEBUG, and TRACE. These log levels represent the severity of the logs:

  • ERROR: For serious errors that may cause the application to abort.
  • WARN: For situations that are not errors but might require attention.
  • INFO: For informational messages that highlight the progress of the application.
  • DEBUG: For lower-level information useful for debugging.
  • TRACE: For very detailed logs, usually of interest only when diagnosing specific problems.

While these default settings are sufficient for many applications, there are scenarios where you need to customize log formats, target specific loggers, or dynamically adjust log levels.

Configuring Logging in Spring Boot

Spring Boot provides several ways to configure logging. The configuration can be done either through application.properties or application.yml files or through more advanced techniques, such as programmatically altering log levels using the LoggingSystem class.

Configuring Logging in application.properties

The simplest way to configure logging in Spring Boot is through the application.properties file. Below are some common configurations:

properties
# Set the root logging level to INFO
logging.level.root=INFO
# Set logging level for specific package or class
logging.level.com.example.myapp=DEBUG# Set a custom logging file
logging.file.name=app-logs.log# Set a rolling policy for log files
logging.file.max-size=10MB
logging.file.max-history=30

These configurations allow you to control the logging level and set file output for your logs. For instance, setting logging.level.root=INFO ensures that all logs at the INFO level and above (INFO, WARN, ERROR) are captured, while debug and trace logs are ignored. You can also specify different logging levels for specific packages or classes as shown in the second property.

Configuring Logging in application.yml

If you prefer to use YAML format for configuration, the equivalent settings are as follows:

yaml
logging:
level:
root: INFO
com.example.myapp: DEBUG
file:
name: app-logs.log
max-size: 10MB
max-history: 30

Testing Log Severity

Once you’ve configured your logging settings, it’s important to test the severity levels. This is where you can log messages at various severity levels and verify whether the application logs behave as expected. Here’s an example using SLF4J in a Spring Boot application:

java
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogTestController {private static final Logger logger = LoggerFactory.getLogger(LogTestController.class);@GetMapping(“/log-test”)
public String logTest() {
logger.error(“This is an ERROR level message”);
logger.warn(“This is a WARN level message”);
logger.info(“This is an INFO level message”);
logger.debug(“This is a DEBUG level message”);
logger.trace(“This is a TRACE level message”);return “Logs generated successfully”;
}
}

In this example, the logTest method logs messages at all severity levels (ERROR, WARN, INFO, DEBUG, TRACE). The application.properties or application.yml settings determine which of these messages actually appear in the logs. If the root level is set to INFO, only INFO, WARN, and ERROR messages will be logged, while DEBUG and TRACE will be ignored.

Adjusting Log Levels Dynamically Using the LoggingSystem Class

Sometimes, you may need to change the log levels dynamically during runtime without restarting the application. This can be particularly useful for production environments when you want to temporarily increase the logging verbosity to troubleshoot an issue.

Spring Boot provides the LoggingSystem class for this purpose, allowing developers to programmatically adjust log levels.

Changing Log Levels Programmatically

You can inject LoggingSystem into any Spring-managed bean and use it to adjust log levels at runtime. Below is an example of how to change the logging level dynamically:

java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.logging.LoggingSystem;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogLevelController {@Autowired
private LoggingSystem loggingSystem;@PostMapping(“/set-log-level”)
public String setLogLevel(@RequestParam String loggerName, @RequestParam String level) {
loggingSystem.setLogLevel(loggerName, LogLevel.valueOf(level.toUpperCase()));
return “Log level for “ + loggerName + ” set to “ + level;
}
}

In this example, the setLogLevel method allows you to change the log level of a specific logger by passing the logger name and desired log level via HTTP parameters. For instance, you can call this endpoint using curl:

bash
curl -X POST "http://localhost:8080/set-log-level?loggerName=com.example.myapp&level=DEBUG"

This command will set the logging level for the com.example.myapp package to DEBUG at runtime without restarting the application.

Getting the Current Log Level

If you want to check the current log level for a logger, you can implement a method to retrieve it:

java
import org.springframework.boot.logging.LogLevel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogLevelQueryController {@Autowired
private LoggingSystem loggingSystem;@GetMapping(“/get-log-level”)
public LogLevel getLogLevel(@RequestParam String loggerName) {
return loggingSystem.getLoggerConfiguration(loggerName).getEffectiveLevel();
}
}

This allows you to check the effective log level for any logger by making an HTTP GET request to /get-log-level?loggerName=com.example.myapp.

Advanced Logging Features in Spring Boot

Using External Configuration Files

Spring Boot allows for externalized logging configuration, where you can use an external file to define your logging setup. For example, if you want to use a custom Logback configuration, you can place a logback-spring.xml file in the src/main/resources directory. Here’s a simple example:

xml
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level=“INFO”>
<appender-ref ref=“CONSOLE” />
</root>
</configuration>

This configuration customizes the log output format and sets the root log level to INFO. You can customize it further with different appenders, loggers, and rolling policies.

Conditional Logging with Profiles

In Spring Boot, you can define logging configurations for different profiles. For instance, you might want more verbose logging in your dev profile and less logging in prod. Here’s how you can set that up:

properties
# application-dev.properties
logging.level.root=DEBUG
# application-prod.properties
logging.level.root=ERROR

When running the application with the dev profile, you’ll get DEBUG logs, while in the prod profile, only ERROR logs will appear.

Conclusion

Logging is a critical component of any Spring Boot application, providing visibility into the internal workings and helping diagnose issues effectively. Spring Boot offers a highly flexible logging system, with default support for Logback, and makes it easy to customize log levels, formats, and output targets.

We explored several ways to configure logging, from simple property-based configurations to programmatically adjusting log levels using the LoggingSystem class. We also covered how to test log severity and dynamically change log settings at runtime.

With these tools, you can fine-tune the logging in your Spring Boot application to meet the specific needs of your development, testing, and production environments, ensuring that your logs are both informative and manageable.

By mastering Spring Boot logging, you not only improve the maintainability of your application but also significantly enhance your ability to troubleshoot and optimize it in real-time.