Master Java Logging: 8 Best Practices to Debug and Optimize Your Applications
A junior developer learns why logging is essential, how to use Logback and Lombok in Spring Boot, choose appropriate log levels, apply parameterized messages, control output volume, format logs, use asynchronous logging, manage log files, and integrate a log collection system for large-scale applications.
You are a new junior programmer tasked with a batch data import program that crashes shortly after launch, leaving you with minimal error information.
Mentor "Fish Skin" introduces you to logging, explaining that logs record program state and help quickly locate issues.
What is Logging?
Fish Skin shows a code example using @Slf4j and log.info to log the start of a batch import, success and failure counts, and per‑user operations.
How to Log?
In Java, you can use built‑in frameworks like Log4j2 or Logback; Spring Boot includes Logback by default.
Obtain a logger instance either manually:
private static final Logger logger = LoggerFactory.getLogger(MyService.class);or via Lombok’s @Slf4j annotation, which automatically generates a log field.
8 Best Practices for Logging
1. Choose Appropriate Log Levels
DEBUG – detailed debugging information
INFO – normal business flow
WARN – potential issues that don’t stop the main flow
ERROR – exceptions or errors
log.debug("User details: {}", userDTO);
log.info("User {} import started", username);
log.warn("User {} email looks suspicious", username);
log.error("User {} import failed", username, e);2. Record Meaningful Information
Use parameterized logging ( {}) instead of string concatenation to avoid unnecessary computation when the log level is disabled.
log.info("User {} started import", username);3. Log at the Right Time
Log entry and exit of important methods, key steps, and handle exceptions with full stack traces.
try {
// business logic
} catch (Exception e) {
log.error("User {} import failed", username, e);
}4. Control Log Output Volume
Log conditionally, e.g., every 100 records, or aggregate messages in a StringBuilder and output once.
if ((i + 1) % 100 == 0) {
log.info("Batch progress: {}/{}", i + 1, userList.size());
}5. Use a Uniform Log Format
Define a pattern in the Logback configuration to include timestamp, thread, level, logger, and message.
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>6. Enable Asynchronous Logging
Configure an AsyncAppender to write logs in a separate thread, reducing impact on request latency.
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<appender-ref ref="FILE" />
</appender>7. Manage Log Files
Use rolling policies to split logs by size and date, keep a limited history, and optionally compress old files.
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>10MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>8. Integrate a Log Collection System
For distributed systems, adopt a centralized solution like the ELK stack (Elasticsearch, Logstash, Kibana) to aggregate, search, and visualize logs across services.
By following these practices, you can turn logs into a powerful tool for debugging, performance monitoring, and operational insight.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
IT Services Circle
Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
