Logging is crucial in any Java application, especially when building production-grade systems using Spring Boot. This guide will take you from the basics of setting up logging configurations in YAML to more advanced topics, ensuring your system is production-ready.
1. Basic Logging Levels
- TRACE: Most detailed information. Rarely used in production.
- DEBUG: Detailed information on application flow. Useful for debugging.
- INFO: General information about application events (e.g., startup).
- WARN: An indication of potential issues.
- ERROR: Error events that might disrupt functionality.
- FATAL: Critical issues causing the application to stop.
2. Setting Up Basic Logging in application.yml
When using YAML for configuration in Spring Boot, you can define logging settings directly in the application.yml
file. Here’s how you can set the root logging level:
logging:
level:
ROOT: INFO
The above configuration sets the default logging level to INFO
for all packages. If you want to specify different logging levels for specific packages or classes, you can extend it as follows:
logging:
level:
com.example: DEBUG
org.springframework: WARN
com.example.service.MyService: ERROR
This configuration sets DEBUG
for the com.example
package, WARN
for org.springframework
, and ERROR
for the specific class MyService
within the com.example.service
package.
3. Configuring a Rolling File Appender
Logging everything to the console is useful during development, but in production, logs should be persisted to files. A rolling file appender is commonly used to manage log files efficiently. You can set this up in application.yml
like this:
logging:
file:
path: /logs/application.log
logback:
rollingpolicy:
max-file-size: 10MB
file-name-pattern: /logs/archived/application-%d{yyyy-MM-dd}.%i.log
max-history: 30
Explanation:
- path: Defines where the log file is stored.
- rollingpolicy: Manages log file rotation based on size and date.
- max-file-size: The maximum size a single log file can reach before rotation.
- file-name-pattern: The pattern for archived log files.
- max-history: The number of days log files are retained.
4. Advanced Log Configuration by Package
For more granular control, you can set different logging levels per package:
logging:
level:
ROOT: WARN
com.filenet.wcm: ERROR
de.mycompany: DEBUG
This sets ERROR
for com.filenet.wcm
and DEBUG
for de.mycompany
. The root level remains at WARN
, and any sub-package logging levels override it as needed.
Common Pitfall: Ensure the syntax follows YAML’s indentation rules. Incorrect spacing can cause parsing errors.
5. Logging Incoming HTTP Requests
To log incoming HTTP requests in Spring Boot, you can use CommonsRequestLoggingFilter
:
logging:
level:
org.springframework.web.filter.CommonsRequestLoggingFilter: DEBUG
Java Configuration:
@Configuration
public class RequestLoggingFilterConfig {
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000);
filter.setIncludeHeaders(false);
filter.setAfterMessagePrefix("REQUEST DATA : ");
return filter;
}
}
This setup logs the query string and payload for each request. It’s especially useful for debugging HTTP calls.
6. Implementing a Custom Log Format
Customizing log formats can enhance readability and make logs more informative:
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n"
This configuration formats logs with a timestamp, log level, thread name, logger name, and the message. You can adjust the pattern to suit your needs.
7. Adding Log Filters
Log filters control what gets logged based on specific criteria. This is particularly helpful when you need to filter out noisy logs:
logging:
level:
org.hibernate: INFO
org.hibernate.SQL: DEBUG
org.hibernate.type: TRACE
This example sets the SQL queries to DEBUG
level and TRACE
for Hibernate type information. Fine-tuning these levels helps reduce log noise while retaining essential information.
8. Integrating Logback-Spring.xml for Advanced Configuration
For scenarios that require more advanced logging setups, you can use logback-spring.xml
instead of YAML. Here’s a basic setup:
logback-spring.xml
:
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/application.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archived/application-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d %-5level [%thread] %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
Switching to XML allows for greater flexibility, like adding multiple appenders or custom log filters.
9. Best Practices for Production-Ready Logging
- Use Proper Log Levels: Set different levels for development (
DEBUG
) and production (WARN
orERROR
) to prevent log flooding in production. - Centralize Logs: Use centralized logging tools (e.g., ELK stack, Graylog) to aggregate logs from different services and make analysis easier.
- Configure Log Rotation: Prevent disk space exhaustion by implementing proper log rotation policies.
- Avoid Sensitive Data: Ensure logs don’t contain sensitive information like passwords, API keys, or personally identifiable information (PII).
10. Dynamic Log Level Changes Without Restarting
Spring Boot allows changing log levels dynamically through Actuator. Add spring-boot-starter-actuator
as a dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Enable the logging endpoint in application.yml
:
management:
endpoints:
web:
exposure:
include: loggers
Now, you can update log levels via HTTP POST:
curl -X POST "http://localhost:8080/actuator/loggers/com.example" -H "Content-Type: application/json" -d '{"configuredLevel": "DEBUG"}'
Conclusion
By following these steps, you can set up a robust logging system that provides the right amount of information without overwhelming your logs. Fine-tune your configurations based on your development and production needs, ensuring your application remains efficient and easy to debug.