SoFunction
Updated on 2025-05-13

Spring Boot Integration SLF4j from Basic to Advanced Practice (Latest Recommendation)

1. Overview of log framework and introduction of SLF4j

1.1 Why logging frameworks are needed

Logging is a crucial component in software development. Imagine you are developing an e-commerce system:

  • When a user fails to place an order, you need to know the specific reason.
  • When there is a bottleneck in system performance, you need to track time-consuming operations
  • When there is a problem with the production environment, you need to troubleshoot the root cause of the error

Without a good logging system, it is like groping in the dark and cannot quickly locate and solve problems.

1.2 Comparison of mainstream log frameworks

Frame Name type Features Applicable scenarios
Log4j accomplish Produced by Apache, powerful functions and flexible configuration Traditional Java Projects
Log4j2 accomplish Log4j upgraded version, better performance and supports asynchronous High performance requirements system
Logback accomplish SLF4j native implementation, excellent performance Spring Boot default
JUL () accomplish JDK built-in, simple functions When restricted by small applications or JDK environments
SLF4j Facade Provide a unified interface and is not responsible for specific implementation Scenarios that require flexibly switching log implementations

1.3 The core value of SLF4j

SLF4j (Simple Logging Facade for Java) is a log facade, not a specific log implementation. It is similar to JDBC, providing a unified API, and the underlying layer can connect to different database drivers.

Advantages of facade mode

  • Decoupling: Business code does not rely on specific log implementation
  • flexible: The underlying log framework can be switched at any time
  • unified: Use a consistent logging API in your project

2. Spring Boot default log configuration

2.1 Log selection for Spring Boot

Spring Boot uses SLF4j + Logback combination by default:

  • SLF4j: Provide a unified logging API
  • Logback: As the default implementation of SLF4j, the performance is better than Log4j

2.2 Basic usage examples

import org.;
import org.;
@RestController
public class OrderController {
    // Use SLF4j's LoggerFactory to get the Logger instance    private static final Logger logger = ();
    @GetMapping("/order/{id}")
    public String getOrder(@PathVariable String id) {
        // Different levels of logging        ("Track order inquiry,OrderID: {}", id);  // The most detailed log        ("Debugging information-OrderID: {}", id);      // Debugging information        ("查询Order,OrderID: {}", id);       // Business information        ("Order查询参数过长,ID: {}", id);    // Warning message        if(() > 20) {
            ("OrderIDException of format: {}", id);    // error message            throw new IllegalArgumentException("Illegal Order ID");
        }
        return "Order Details";
    }
}

2.3 Detailed explanation of log level

SLF4j defines 6 log levels (from low to high):

level meaning Use scenarios Whether to output by default
TRACE track The most detailed log information, record every step of the program execution no
DEBUG debug Debugging information, use in the development stage no
INFO information Important business process information yes
WARN warn Potential problems do not affect system operation yes
ERROR mistake Error message affects some functions yes
FATAL fatal Serious error causing system crash Yes (Logback does not have this level and will be mapped to ERROR)

3. Detailed explanation of SLF4j configuration file

3.1 Default configuration and customization

Spring Boot will look for the following log configuration files under classpath by default:

  • (recommend)

Why is it recommended to use

Because it supports the Profile feature of Spring Boot, different configurations can be loaded according to different environments.

3.2 Complete configuration file analysis

Here is a complete oneExample, we parse in segments:

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    <!-- Define variables -->
    <property name="LOG_HOME" value="./logs" />
    <property name="APP_NAME" value="my-application" />
    <property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:} [%thread] %-5level %logger{36} - %msg%n" />
    <!-- Console output -->
    <appender name="CONSOLE" class="">
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- The console outputs onlyINFOLevels above -->
        <filter class="">
            <level>INFO</level>
        </filter>
    </appender>
    <!-- Scroll file output -->
    <appender name="FILE" class="">
        <file>${LOG_HOME}/${APP_NAME}.log</file>
        <encoder>
            <pattern>${LOG_PATTERN}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- Scrolling strategy -->
        <rollingPolicy class="">
            <!-- Scroll by date and size -->
            <fileNamePattern>${LOG_HOME}/${APP_NAME}-%d{yyyy-MM-dd}.%</fileNamePattern>
            <!-- Maximum single file100MB -->
            <maxFileSize>100MB</maxFileSize>
            <!-- reserve30Day Log -->
            <maxHistory>30</maxHistory>
            <!-- The total size does not exceed5GB -->
            <totalSizeCap>5GB</totalSizeCap>
        </rollingPolicy>
    </appender>
    <!-- Asynchronous logs -->
    <appender name="ASYNC" class="">
        <!-- Threshold for not losing logs,default256 -->
        <queueSize>512</queueSize>
        <!-- Add additionalappender -->
        <appender-ref ref="FILE" />
    </appender>
    <!-- Log level settings -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ASYNC" />
    </root>
    <!-- Specific package/Class log level -->
    <logger name="" level="DEBUG" />
    <logger name="" level="WARN" />
    <!-- Production environment specific configuration -->
    <springProfile name="prod">
        <root level="WARN">
            <appender-ref ref="CONSOLE" />
            <appender-ref ref="ASYNC" />
        </root>
    </springProfile>
    <!-- Development environment specific configuration -->
    <springProfile name="dev">
        <root level="DEBUG">
            <appender-ref ref="CONSOLE" />
        </root>
    </springProfile>
</configuration>

3.3 Detailed explanation of configuration elements

3.3.1 Properties

<property name="LOG_HOME" value="./logs" />
property illustrate Example Values necessity
name Attribute name LOG_HOME Required
value Attribute value ./logs Required
scope Scope context/system Optional

3.3.2 Output source (Appender)

1. Console output (ConsoleAppender)

<appender name="CONSOLE" class="">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

2. File output (RollingFileAppender)

<appender name="FILE" class="">
    <file>${LOG_HOME}/${APP_NAME}.log</file>
    <rollingPolicy class="">
        <fileNamePattern>${LOG_HOME}/${APP_NAME}-%d{yyyy-MM-dd}.%</fileNamePattern>
        <maxFileSize>100MB</maxFileSize>
        <maxHistory>30</maxHistory>
    </rollingPolicy>
</appender>

Comparison of scrolling strategies

Strategy illustrate Applicable scenarios
TimeBasedRollingPolicy Scroll by time Logs need to be split by day/hour
SizeBasedTriggeringPolicy Scroll by size Need to limit the size of a single log file
SizeAndTimeBasedRollingPolicy Dual strategy of time and size Split by time and size

3.3.3 Log format (Pattern)

The log format consists of converters, commonly used converters:

Strategy illustrate Applicable scenarios
TimeBasedRollingPolicy Scroll by time Logs need to be split by day/hour
SizeBasedTriggeringPolicy Scroll by size Need to limit the size of a single log file
SizeAndTimeBasedRollingPolicy Dual strategy of time and size Split by time and size

3.3.4 Filter

<filter class="">
    <level>ERROR</level>
    <onMatch>ACCEPT</onMatch>
    <onMismatch>DENY</onMismatch>
</filter>

Commonly used filters:

Filter class Function parameter
LevelFilter Precise matching level level, onMatch, onMismatch
ThresholdFilter Threshold filtering, record only if it is above or equal to this level level
EvaluatorFilter Use expression filtering evaluator

3.3.5 Asynchronous logs (AsyncAppender)

<appender name="ASYNC" class="">
    <queueSize>512</queueSize>
    <discardingThreshold>0</discardingThreshold>
    <appender-ref ref="FILE" />
</appender>

Parameter description

parameter illustrate default value Suggested value
queueSize Queue size 256 512-2048
discardingThreshold When the remaining queue capacity is less than this value, discard the TRACE/DEBUG log queueSize/5 0(Don't discard)
includeCallerData Whether to include caller information false Production environment false (performance considerations)

4. Advanced features and best practices

4.1 MDC (Mapped Diagnostic Context)

MDC is used to save thread context information in logs and is very suitable for web request tracking.

Example: Add a request ID to the log

import org.;
@RestController
public class OrderController {
    @GetMapping("/order/{id}")
    public String getOrder(@PathVariable String id) {
        // Set the MDC value        ("requestId", ().toString());
        ("userId", "user123");
        try {
            ("Inquiry of orders: {}", id);
            // Business logic...            return "Order details";
        } finally {
            // Clear MDC            ();
        }
    }
}

Reference to MDC in logback configuration

<pattern>%d{yyyy-MM-dd HH:mm:} [%thread] [%X{requestId}] %-5level %logger{36} - %msg%n</pattern>

4.2 Log performance optimization

Parameterized log

Avoid string splicing and use placeholders:

// Not recommended("User " + userId + " login from " + ip);
// recommend("User {} login from {}", userId, ip);

isXXXEnabled judgment

For high overhead logs:

if(()) {
    ("Large data: {}", expensiveOperation());
}

Asynchronous logs

As in the previous example, use AsyncAppender to reduce I/O blocking

4.3 Multi-environment configuration

Use Spring Profile to implement differentiated configuration in the environment:

&lt;!-- Development Environment --&gt;
&lt;springProfile name="dev"&gt;
    &lt;root level="DEBUG"&gt;
        &lt;appender-ref ref="CONSOLE" /&gt;
    &lt;/root&gt;
&lt;/springProfile&gt;
&lt;!-- Production environment --&gt;
&lt;springProfile name="prod"&gt;
    &lt;root level="INFO"&gt;
        &lt;appender-ref ref="FILE" /&gt;
        &lt;appender-ref ref="SENTRY" /&gt;
    &lt;/root&gt;
&lt;/springProfile&gt;

4.4 Log monitoring and alarm

Integrated Sentry implementation error monitoring:

<!-- Sentry Appender -->
<appender name="SENTRY" class="">
    <filter class="">
        <level>ERROR</level>
    </filter>
</appender>

5. Frequently Asked Questions and Solutions

5.1 Log conflict issues

Problem phenomenon: SLF4j report an errorSLF4J: Class path contains multiple SLF4J bindings

Solution:usemvn dependency:treeCheck dependencies and exclude unnecessary log implementations

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <exclusions>
        <exclusion>
            <groupId></groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </exclusion>
    </exclusions>
</dependency>

5.2 Log files are not generated

Check steps

  • Confirm the configuration file location is correct (under the resources directory)
  • Check whether the file path has write permissions
  • Check whether there is any exception log output
  • Confirm that Appender is cited<appender-ref ref="FILE" />

5.3 The log level does not take effect

Possible Causes

  • Configuration overwritten (check multiple configuration files)
  • Package path configuration error
  • Configuration not reloaded after modification (settingsscan="true"

6. Practical case: E-commerce system log design

6.1 Log classification design

Log Type level Output target content
Access log INFO Log all HTTP requests
Business Log INFO Core business operations
Error log ERROR System exceptions and errors
SQL Logs DEBUG SQL statements and parameters
Performance Log INFO Interface time-consuming statistics

6.2 Complete configuration example

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;configuration&gt;
    &lt;!-- Public properties --&gt;
    &lt;property name="LOG_HOME" value="/var/logs/ecommerce" /&gt;
    &lt;property name="APP_NAME" value="ecommerce" /&gt;
    &lt;!-- publicPattern --&gt;
    &lt;property name="COMMON_PATTERN" 
              value="%d{yyyy-MM-dd HH:mm:} [%X{requestId}] [%thread] %-5level %logger{36} - %msg%n" /&gt;
    &lt;!-- Console output --&gt;
    &lt;appender name="CONSOLE" class=""&gt;
        &lt;encoder&gt;
            &lt;pattern&gt;${COMMON_PATTERN}&lt;/pattern&gt;
        &lt;/encoder&gt;
    &lt;/appender&gt;
    &lt;!-- Access log --&gt;
    &lt;appender name="ACCESS" class=""&gt;
        &lt;file&gt;${LOG_HOME}/&lt;/file&gt;
        &lt;encoder&gt;
            &lt;pattern&gt;%d{yyyy-MM-dd HH:mm:} [%X{requestId}] %msg%n&lt;/pattern&gt;
        &lt;/encoder&gt;
        &lt;rollingPolicy class=""&gt;
            &lt;fileNamePattern&gt;${LOG_HOME}/access.%d{yyyy-MM-dd}.log&lt;/fileNamePattern&gt;
            &lt;maxHistory&gt;30&lt;/maxHistory&gt;
        &lt;/rollingPolicy&gt;
    &lt;/appender&gt;
    &lt;!-- Error log --&gt;
    &lt;appender name="ERROR" class=""&gt;
        &lt;file&gt;${LOG_HOME}/&lt;/file&gt;
        &lt;encoder&gt;
            &lt;pattern&gt;${COMMON_PATTERN}&lt;/pattern&gt;
        &lt;/encoder&gt;
        &lt;rollingPolicy class=""&gt;
            &lt;fileNamePattern&gt;${LOG_HOME}/error.%d{yyyy-MM-dd}.%&lt;/fileNamePattern&gt;
            &lt;maxFileSize&gt;100MB&lt;/maxFileSize&gt;
            &lt;maxHistory&gt;60&lt;/maxHistory&gt;
        &lt;/rollingPolicy&gt;
        &lt;filter class=""&gt;
            &lt;level&gt;ERROR&lt;/level&gt;
        &lt;/filter&gt;
    &lt;/appender&gt;
    &lt;!-- asynchronousAppender --&gt;
    &lt;appender name="ASYNC_ERROR" class=""&gt;
        &lt;queueSize&gt;1024&lt;/queueSize&gt;
        &lt;appender-ref ref="ERROR" /&gt;
    &lt;/appender&gt;
    &lt;!-- Log level configuration --&gt;
    &lt;root level="INFO"&gt;
        &lt;appender-ref ref="CONSOLE" /&gt;
    &lt;/root&gt;
    &lt;!-- Access logLogger --&gt;
    &lt;logger name="ACCESS_LOG" level="INFO" additivity="false"&gt;
        &lt;appender-ref ref="ACCESS" /&gt;
    &lt;/logger&gt;
    &lt;!-- Error logLogger --&gt;
    &lt;logger name="ERROR_LOG" level="ERROR" additivity="false"&gt;
        &lt;appender-ref ref="ASYNC_ERROR" /&gt;
    &lt;/logger&gt;
    &lt;!-- MyBatis SQLlog --&gt;
    &lt;logger name="" level="DEBUG" additivity="false"&gt;
        &lt;appender-ref ref="SQL" /&gt;
    &lt;/logger&gt;
&lt;/configuration&gt;

6.3 AOP implementation access log

@Aspect
@Component
public class AccessLogAspect {
    private static final Logger accessLog = ("ACCESS_LOG");
    @Around("execution(* ..*.*(..))")
    public Object logAccess(ProceedingJoinPoint joinPoint) throws Throwable {
        HttpServletRequest request = 
            ((ServletRequestAttributes) ()).getRequest();
        // Record request information        String requestId = ().toString();
        ("requestId", requestId);
        long start = ();
        try {
            Object result = ();
            long cost = () - start;
            ("method={} uri={} status=success cost={}ms ip={} params={}",
                         (),
                         (),
                         cost,
                         (),
                         ());
            return result;
        } catch (Exception e) {
            long cost = () - start;
            ("method={} uri={} status=error cost={}ms error={}",
                          (),
                          (),
                          cost,
                          ());
            throw e;
        } finally {
            ();
        }
    }
}

7. Summary

7.1 Summary of key points

  • Unified use of SLF4j API: Keep code decoupling from specific implementations
  • Reasonable configuration of log levels: production environment is usually INFO, development environment DEBUG
  • Log file segmentation strategy: split by time and size
  • Enhanced logs with MDC: Add request tracking information
  • Performance optimization: asynchronous log, parameterized log, isXXXEnabled judgment
  • Multi-environment support: Use Profile to achieve differentiated configuration

This is the article about Spring Boot Integration SLF4j from basic to advanced practice (latest recommendation). For more related Spring Boot Integration SLF4j content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!