Master Spring Boot Logging: 12 Practical Guidelines for High‑Performance Apps
This article presents twelve concrete guidelines and code examples for configuring Spring Boot 3 logging—covering readability, level selection, structured JSON output, asynchronous handling, sensitive data masking, and log rotation—to help developers build observable, maintainable, and high‑performance backend services.
1. Introduction
In the era of distributed systems and micro‑service architecture, the amount of log data generated by Spring Boot applications grows exponentially. Logs are not only the "black box" for troubleshooting, but also the core basis for system health monitoring, security auditing, and performance optimization. Improper log configuration in production often leads to storage explosion, sensitive data leakage, and missing debug information. This article summarizes twelve guidelines covering framework selection, level control, structured output, and performance optimization, helping developers build observable, maintainable, high‑performance logging systems.
2. Practical Cases
2.1 Readable Logs
Many developers think "logs are for troubleshooting", but who will actually read them? Most logs are ignored or only consulted when a problem occurs. When writing each log statement, imagine a colleague at 3 am searching through the sea of logs.
// Poor log example
log.info("Processing start");
// ... business logic ...
log.info("Processing end");
// Improved log
log.info("Start processing user payment request. userId={}, orderId={}, amount={}", userId, orderId, amount);
// ... business logic ...
log.info("User payment request completed. userId={}, orderId={}, result={}", userId, orderId, result);2.2 Vague Advice: Don’t Just "Add More Logs"
Simply increasing log volume does not always solve problems; the content, level, and destination must be considered. Indiscriminate logging can drown valuable information. Example of a Java project generating 50 MB of logs in five minutes, consisting only of repetitive debug statements.
log.debug("Entering method A");
log.debug("Exiting method A");
log.debug("Entering method B");
log.debug("Exiting method B");
// ...Each log line incurs storage, I/O, and reading costs.
2.3 User‑Centric vs Developer‑Centric Logs
Most logs are written from a developer’s perspective, e.g.
log.info("Data processing completed, preparing to add to cache.");A business‑oriented log should include domain information:
log.info("User {}'s order {} status changed from {} to {}", userId, orderId, oldStatus, newStatus);2.4 Misusing ERROR Level
Developers often log every caught exception as ERROR, even when the exception is an expected business scenario. Example of proper level selection:
try {
// TODO
} catch (InvalidCredentialsException e) {
// Expected business case – use INFO
log.info("User {} login failed: incorrect password", username);
return ...;
} catch (Exception e) {
// Unexpected – use ERROR
log.error("User {} encountered system exception during login: {}", username, e);
return ...;
}Guideline for levels:
ERROR – issues requiring manual intervention.
WARN – problems that may become ERROR if not addressed.
INFO – important business milestones.
DEBUG/TRACE – temporary troubleshooting, usually disabled in production.
2.5 Avoid Logging Inside Loops
// Bad practice
for (Item item : items) {
logger.info("Processing item: {}", item); // thousands of lines
}
// Improved version
logger.info("Preparing to process {} items", items.size());
// processing logic
logger.info("Finished processing {} items. success={}, fail={}", items.size(), successCount, failCount);2.6 Use Placeholders Instead of String Concatenation
// Wrong
log.debug("Processing user: " + user.getName() + ", ID: " + user.getId());
// Correct
log.debug("Processing user: {}, ID: {}", user.getName(), user.getId());2.7 Handle Large Objects Carefully
// Dangerous
log.debug("User data: {}", user);
// Better
log.debug("User basic info: id={}, name={}, type={}", user.getId(), user.getName(), user.getType());2.8 Sensitive Data Masking
Never log passwords, tokens, personal identifiers, etc. Use masking or dedicated utilities.
// Unsafe
log.info("User login: username={}, password={}", username, password);
// Safe
log.info("User login: username={}, password=****", username);
// Or
log.info("User info: {}", LogSensitiveUtils.mask(userInfo));2.9 JSON Log Format
Add Logstash encoder dependency and configure Logback to output JSON.
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>8.0</version>
</dependency> <appender name="TRACEX" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>2.10 Asynchronous Logging
Logging is I/O‑intensive. Asynchronous appenders reduce latency.
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="TRACEX"/>
<queueSize>512</queueSize>
<discardingThreshold>0</discardingThreshold>
<includeCallerData>false</includeCallerData>
</appender>2.11 High‑Concurrency Logging Strategies
Sampling: log detailed info for a small percentage of requests.
Batch logging: aggregate multiple entries into a single write.
Non‑blocking queues (e.g., Disruptor).
Increase buffer size to reduce disk flush frequency.
// Simple sampling
if (Math.random() < 0.01) { // 1% sample rate
logger.info("Detailed request: request={}, headers={}", request, headers);
}2.12 Log Rotation and Archiving
Log files cannot grow indefinitely; define a rotation policy.
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>app-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d %p %c{1} [%t] %m%n</pattern>
</encoder>
</appender>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.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.
