Boost Spring Boot Performance: Master Logback Async Logging & File Segmentation

Learn how to configure Logback in Spring Boot to separate logs by level, implement asynchronous logging for reduced I/O latency, and verify performance gains—up to tenfold throughput improvement—using JMeter tests on a six‑core, 8 GB server, with detailed XML snippets and code explanations.

Programmer DD
Programmer DD
Programmer DD
Boost Spring Boot Performance: Master Logback Async Logging & File Segmentation

01 What You Will Learn

Log output to files and categorize them by LEVEL for separate storage.

Reduce disk IO by using asynchronous logging to improve performance.

Understand the principle behind asynchronous log output.

02 Configure logback-spring.xml

A Spring Boot project already includes logback and slf4j dependencies, so you only need to write the configuration file. Logback automatically loads a file named logback-spring.xml or logback.xml from the classpath. Instead of storing all logs in a single growing file, you should separate error logs from other levels and rotate logs by time.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <property resource="logback.properties"/>
    <appender name="CONSOLE-LOG" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
        </layout>
    </appender>
    <!-- Appender for INFO and higher (excluding ERROR) -->
    <appender name="INFO-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>DENY</onMatch>
            <onMismatch>ACCEPT</onMismatch>
        </filter>
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
        </encoder>
        <!-- Rolling policy -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_INFO_HOME}/%d.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    <appender name="ERROR-LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%C] [%t] [%L] [%-5p] %m%n</pattern>
        </encoder>
        <!-- Rolling policy -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_ERROR_HOME}/%d.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    <root level="info">
        <appender-ref ref="CONSOLE-LOG"/>
        <appender-ref ref="INFO-LOG"/>
        <appender-ref ref="ERROR-LOG"/>
    </root>
</configuration>

Key tags explained: <root>: mandatory tag that sets the base logging level. <appender-ref>: adds an appender to the logger. name attribute: names the appender. class attribute: specifies the output strategy, e.g., ConsoleAppender for console output or a file appender for persistence. <filter>: defines a filtering strategy, such as <level> to filter by log level. <encoder> with <pattern>: sets the log format. <rollingPolicy>: configures time‑based log rotation.

03 Logback Advanced Feature: Asynchronous Logging

Traditional logging is synchronous, causing a disk I/O operation for each log entry. By adding an asynchronous appender that references the original file appender, you can avoid blocking the application thread.

<!-- Async output -->
<appender name="ASYNC-INFO" class="ch.qos.logback.classic.AsyncAppender">
    <!-- Do not discard logs; default discarding threshold is 0 -->
    <discardingThreshold>0</discardingThreshold>
    <!-- Queue depth (default 256) can be tuned for performance -->
    <queueSize>256</queueSize>
    <!-- Reference the original INFO appender -->
    <appender-ref ref="INFO-LOG"/>
</appender>

<appender name="ASYNC-ERROR" class="ch.qos.logback.classic.AsyncAppender">
    <discardingThreshold>0</discardingThreshold>
    <queueSize>256</queueSize>
    <appender-ref ref="ERROR-LOG"/>
</appender>

04 Asynchronous Logging Performance Test

To verify the performance gain, a JMeter test with 100 concurrent threads and a ramp‑up of 0 seconds was conducted.

Synchronous Logging

Throughput (TPS) was 44.2 requests/second.

Sync logging result
Sync logging result

Asynchronous Logging

Throughput (TPS) increased to 497.5 requests/second, more than ten times faster.

Async logging result
Async logging result

05 Server Hardware

CPU: six cores

Memory: 8 GB

06 Test Tool

Apache JMeter was used for the load test.

07 Synchronous Logging Details

Thread count: 100

Ramp‑up: 0 (all threads start simultaneously)

Result image shown above.

08 Asynchronous Logging Details

Thread count: 100

Ramp‑up: 0

Result image shown above.

09 Asynchronous Logging Principle

The flow starts from Logger.info in Logback, which quickly enqueues the log event. The AsyncAppenderBase uses an ArrayBlockingQueue (default size 256, configurable) to hold events.

protected void append(E eventObject) {
    if (!this.isQueueBelowDiscardingThreshold() || !this.isDiscardable(eventObject)) {
        this.preprocess(eventObject);
        this.put(eventObject);
    }
}

A dedicated worker thread takes events from the queue and forwards them to the attached appenders:

E e = parent.blockingQueue.take();
aai.appendLoopOnAppenders(e);

The worker ultimately calls the encode and write methods of each appender to persist the log.

Async logging flow diagram
Async logging flow diagram
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.

Performance Testingasynchronous loggingspring-boot
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.