One Bad Log Can Halve Spring Boot Throughput – How to Log Without Losing Performance

The article explains why effective logging is crucial for Java applications, compares proper and improper logging practices with SLF4J and Logback, and provides fourteen concrete best‑practice guidelines—including correct logger setup, level usage, placeholders, asynchronous and structured logging—to avoid performance degradation and security risks.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
One Bad Log Can Halve Spring Boot Throughput – How to Log Without Losing Performance

Effective logging is a vital component of any Java application, providing observability, faster fault isolation, enhanced event response, and compliance support, especially in production environments.

Benefits of proper logging

Improved observability through detailed runtime records.

Accelerated troubleshooting by pinpointing root causes.

Better incident response with chronological event traces.

Compliance and security evidence for audits.

Choosing SLF4J and Logback

SLF4J is a popular logging façade that decouples application code from the underlying logging implementation. Logback is a widely used backend offering rich features and configurability. Combining them yields flexibility and powerful logging capabilities.

Best Practices

2.1 Use SLF4J as the logging façade

Correct

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
}

Incorrect

import org.apache.log4j.Logger;

public class UserController {
    private static final Logger logger = Logger.getLogger(UserController.class);
}

2.2 Configure Logback

Correct

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <root level="debug">
    <appender-ref ref="STDOUT" />
  </root>
</configuration>

Incorrect

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- Deprecated layout class -->
    <layout class="ch.qos.logback.classic.PatternLayout">
    </layout>
  </appender>
</configuration>

2.3 Use appropriate log levels

Correct

logger.info("Application has started.");
logger.debug("The value of X is {}", x);
logger.error("Unable to process the request.", e);

Incorrect

logger.error("xxxooo."); // misuse of level
logger.error("x = " + x); // inefficient string concatenation

2.4 Log meaningful information

Correct

logger.info("Order ID: {}", orderId);

Incorrect

logger.info("This is my info."); // meaningless

2.5 Use placeholders for dynamic content

Correct

logger.info("User {} logged in at {}", username, LocalDateTime.now());

Incorrect

logger.debug("User " + username + " logged in at " + LocalDateTime.now());

If the logger level is INFO, the concatenation still occurs, so placeholders should be used to avoid unnecessary computation.

2.6 Record stack traces for exceptions

Correct

try {
    // ...
} catch (Exception e) {
    logger.error("Payment exception: {}", e);
}

Incorrect

try {
    // ...
} catch (Exception e) {
    logger.error("Payment exception: {}", e.getMessage());
}

2.7 Use asynchronous logging

Correct

<configuration>
  <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
    <appender-ref ref="FILE" />
  </appender>
  <appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>application.log</file>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="ASYNC" />
  </root>
</configuration>

Asynchronous logging moves the I/O work to a separate thread, improving application performance.

2.8 Log with appropriate granularity

Correct

public void processOrder(Order order) {
    logger.info("Processing order: {}", order.getId());
    logger.debug("Order details: {}", order);
    orderRepository.save(order);
    logger.info("Order processed successfully");
}

Incorrect

public void processOrder(Order order) {
    logger.trace("开始处理订单");
    logger.debug("订单新: {}", order);
    logger.info("准备处理订单: {}", order.getId());
    logger.debug("Step 1: 校验订单有效性");
    // ...
    logger.info("订单处理成功");
}

Excessive high‑granularity logs in production can cause performance issues and log flooding.

2.9 Monitor and rotate log files

Correct

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <fileNamePattern>logs/myapp-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
    <maxHistory>30</maxHistory>
    <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
      <maxFileSize>100MB</maxFileSize>
    </timeBasedFileNamingAndTriggeringPolicy>
  </rollingPolicy>
</appender>

Incorrect

// No rotation – log files grow without bound, eventually exhausting disk space.

2.10 Protect sensitive information

Correct

log.info("Payment card: {}", maskCreditCard(creditCardNumber));

public String maskCreditCard(String creditCardNumber) {
    int length = creditCardNumber.length();
    if (length < 4) return "Invalid number";
    return "****-****-****-" + creditCardNumber.substring(length - 4);
}

Incorrect

logger.info("Payment card: {}", creditCardNumber); // logs raw sensitive data

2.11 Structured logging

Correct

<configuration>
  <appender name="JSON_CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
      <providers>
        <timestamp><timeZone>UTC</timeZone></timestamp>
        <version />
        <logLevel />
        <threadName />
        <loggerName />
        <message />
        <context />
        <StackTrace />
      </providers>
    </encoder>
  </appender>
  <root level="info">
    <appender-ref ref="JSON_CONSOLE" />
  </root>
</configuration>

Example output:

{"@timestamp":"2024-10-26 15:52:34","@version":"1","message":"Order processing completed","logger_name":"Application","thread_name":"main","level":"INFO"}

Incorrect – using unstructured plain‑text logs makes automated parsing difficult.

2.12 Integrate with monitoring tools

Correct – connect logging to monitoring and alerting systems to automatically detect anomalies.

Incorrect – ignoring integration delays problem discovery.

2.13 Log aggregation

Correct – use centralized log aggregation in distributed environments to simplify analysis.

Incorrect – scattered logs across services complicate troubleshooting.

2.14 Intelligent logging with AOP

Example of using Spring AOP to log method execution:

@Component
@Aspect
public class LogAspect {
    @Pointcut("@target(pack)")
    private void log(Pack pack) {}

    @Around("log(pack)")
    public Object around(ProceedingJoinPoint pjp, Pack pack) throws Throwable {
        System.err.println("before...");
        Object ret = pjp.proceed();
        System.err.println("after...");
        return ret;
    }
}

Following these practices helps maintain high observability while preserving application performance and security.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSpring BootLogbackstructured loggingSLF4Jasynchronous logginglogging best practices
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.