SoFunction
Updated on 2025-04-10

SpringBoot project injection traceId tracks the log link of the entire request (process details)

SpringBoot project injects traceId to track the log link of the entire request. With traceId, when we troubleshoot problems, we can quickly find the logs of the relevant requests based on the traceId. Especially in the production environment, the user may only provide an error screenshot. As developers, we want more detailed logs. At this time, we can directly search the entire log of the user's request based on the traceId provided by the user, which will be much more convenient.

Can't springboot single-body project have the same effect as traceId?

Even in monolithic applications, it is perfectly feasible to add a unique traceId to the request to track the logs of the entire request link. Although tools such as Spring Cloud Sleuth are mainly used for link tracing in distributed systems, you can still achieve similar functions in a single Spring Boot application through some methods. Here is a basic method to manually implement such functions:

Manually implement traceId injection

1. Create a filter or interceptor: You can create a Servlet filter or Spring interceptor to generate a unique traceId (if not present) when each request arrives and store it in the context of the current thread.

2. Use MDC (Mapped Diagnostic Context): SLF4J provides an MDC tool that can be used to save context information of logs. You can put traceId into the MDC in the filter or interceptor so that all loggers can automatically include this ID. Sample code:

TraceIdFilter :

# I am using jdk17 here, so the servlet tool class has been moved to the jakarta package. If you are using older jdk, you can delete it and re-import the servlet class.import ;
import ;
import ;
import ;
import org.;
import ;
import ;
import ;
import ;
@Compone
nt
public class TraceIdFilter extends OncePerRequestFilter {
    private static final String TRACE_ID = "traceId";
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String traceId = (TRACE_ID);
        if (traceId == null) {
            traceId = ().toString();
        }
        (TRACE_ID, traceId);
        try {
            (request, response);
        } finally {
            (TRACE_ID);
        }
    }
}

3. Configure log format: Make sure that your log configuration file (such as, etc.) contains the configuration of output traceId. For example, in logback you can do this:

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

My project uses , and the complete content of my file is as follows:
:

&lt;configuration debug="true"&gt;
    &lt;!-- QuoteSpring BootDate format configuration items in global configuration files --&gt;
    &lt;springProperty scope="context" name="dateformat" source="" defaultValue="yyyy-MM-dd HH:mm:"/&gt;
    &lt;springProperty scope="context" name="APP_NAME"  source=""/&gt;
    &lt;springProperty scope="context" name="LOG_FILE"  source=""/&gt;
    &lt;!-- Define color code --&gt;
    &lt;conversionRule conversionWord="clr" converterClass=""/&gt;
    &lt;conversionRule conversionWord="wEx" converterClass=""/&gt;
    &lt;!-- Define log output to consoleappender --&gt;
    &lt;appender name="STDOUT" class=""&gt;
        &lt;encoder&gt;
            &lt;pattern&gt;%clr(%d{${dateformat}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr([%15.15t]){faint} [%-40.40logger{39}] [%X{traceId}] %clr(%msg%n){faint}%wEx&lt;/pattern&gt;
        &lt;/encoder&gt;
    &lt;/appender&gt;
    &lt;!-- Development environment configuration --&gt;
    &lt;springProfile name="local | test"&gt;
        &lt;root level="DEBUG"&gt;
            &lt;appender-ref ref="STDOUT" /&gt;
        &lt;/root&gt;
        &lt;!-- Detailed logs exclusive to the development environment --&gt;
        &lt;logger name="" level="TRACE" additivity="false"&gt;
            &lt;appender-ref ref="STDOUT" /&gt;
        &lt;/logger&gt;
    &lt;/springProfile&gt;
    &lt;springProfile name="dev | prod"&gt;
        &lt;!-- File log:Output all logs to files --&gt;
        &lt;appender name="FILE_INFO_LOG" class=""&gt;
            &lt;file&gt;${LOG_FILE}/${APP_NAME}.log&lt;/file&gt;
            &lt;filter class=""&gt;
                &lt;level&gt;ERROR&lt;/level&gt;
                &lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;
                &lt;onMismatch&gt;ACCEPT&lt;/onMismatch&gt;
            &lt;/filter&gt;
            &lt;rollingPolicy class=""&gt;
                &lt;fileNamePattern&gt;${LOG_FILE}/${APP_NAME}.%d{yyyy-MM-dd}.%&lt;/fileNamePattern&gt;
                &lt;maxHistory&gt;180&lt;/maxHistory&gt;
                &lt;timeBasedFileNamingAndTriggeringPolicy class=""&gt;
                    &lt;maxFileSize&gt;50MB&lt;/maxFileSize&gt;
                &lt;/timeBasedFileNamingAndTriggeringPolicy&gt;
            &lt;/rollingPolicy&gt;
            &lt;encoder class=""&gt;
                &lt;pattern&gt;%d{${dateformat}} [%thread] %-5level %logger{36} [%X{traceId}] - %msg%n&lt;/pattern&gt;
                &lt;charset&gt;UTF-8&lt;/charset&gt;
            &lt;/encoder&gt;
        &lt;/appender&gt;
        &lt;!-- Error log:用于将Error log输出到独立文件 --&gt;
        &lt;appender name="FILE_ERROR_LOG" class=""&gt;
            &lt;file&gt;${LOG_FILE}/error-${APP_NAME}.log&lt;/file&gt;
            &lt;filter class=""&gt;
                &lt;level&gt;ERROR&lt;/level&gt;
                &lt;onMatch&gt;ACCEPT&lt;/onMatch&gt;
                &lt;onMismatch&gt;DENY&lt;/onMismatch&gt;
            &lt;/filter&gt;
            &lt;rollingPolicy class=""&gt;
                &lt;fileNamePattern&gt;${LOG_FILE}/error-${APP_NAME}.%d{yyyy-MM-dd}.%&lt;/fileNamePattern&gt;
                &lt;maxHistory&gt;180&lt;/maxHistory&gt;
                &lt;timeBasedFileNamingAndTriggeringPolicy class=""&gt;
                    &lt;maxFileSize&gt;50MB&lt;/maxFileSize&gt;
                &lt;/timeBasedFileNamingAndTriggeringPolicy&gt;
            &lt;/rollingPolicy&gt;
            &lt;encoder class=""&gt;
                &lt;pattern&gt;%d{${dateformat}} [%thread] %-5level %logger{36} [%X{traceId}] - %msg%n&lt;/pattern&gt;
                &lt;charset&gt;UTF-8&lt;/charset&gt;
            &lt;/encoder&gt;
        &lt;/appender&gt;
        &lt;root level="INFO"&gt;
            &lt;appender-ref ref="STDOUT" /&gt;
            &lt;appender-ref ref="FILE_INFO_LOG" /&gt;
            &lt;appender-ref ref="FILE_ERROR_LOG" /&gt;
        &lt;/root&gt;
    &lt;/springProfile&gt;
&lt;/configuration&gt;

For more specific log output configuration, please refer to this article in my article"Sample Explanation of SpringBoot Configuration Log4j Output Log".

In this way, you can generate a unique traceId for each request in a monolithic Spring Boot project and output it through the log, thus achieving the effect that all log entries during the process of the request. This approach is not only suitable for monolithic applications, but also serves as a basis for understanding more complex concepts of distributed tracking.

After this configuration, you will carry traceId when printing the log in the code.

 ("Request parameters: {}", arg);

Output example:

2025-02-26 19:25:02.187 INFO [nio-8070-exec-2] [       ] [ab85097a-6d31-44c3-bcfb-2bcc97b87ab9] Method: (..)

Of course, we not only need to output traceId to the console, but also need to return traceId to the front-end user. In this way, when the user asks us to troubleshoot problems, we only need to give us a traceId.

So inject traceId into the returned wrapper class and return it to the front end.
My code is as follows:

import ;
import ;
import org.;
@Getter
@NoArgsConstructor
public class Result&lt;T&gt; {
    private int code;
    private boolean flag;
    private String desc;
    private String cause;
    private String traceId;
    private T data;
    public Result(int code, boolean flag, String desc) {
         = code;
         = flag;
         = desc;
    }
    public Result(int code, boolean flag, String desc, String traceId) {
         = code;
         = flag;
         = desc;
         = traceId;
    }
    public Result(int code, boolean flag, String desc, String cause, String traceId) {
         = code;
         = flag;
         = desc;
         = cause;
         = traceId;
    }
    public Result(int code, boolean flag, String desc, T data, String traceId) {
         = code;
         = flag;
         = desc;
         = data;
         = traceId;
    }
    public static &lt;T&gt; Result&lt;T&gt; success() {
        return new Result&lt;&gt;(0, true, "success", ("traceId"));
    }
    public static &lt;T&gt; Result&lt;T&gt; success(T data) {
        return new Result&lt;&gt;(0, true,"success", data, ("traceId"));
    }
    public static &lt;T&gt; Result&lt;T&gt; fail(int code, String desc, String cause) {
        return new Result&lt;&gt;(code, false, desc, cause, ("traceId"));
    }
}

Example of failure returned to the front end:

{
    "code": 405,
    "flag": false,
    "desc": "The request method is not supported.",
    "cause": "Request method 'POST' is not supported",
    "traceId": "ebd77e99-361c-47b3-8569-2d321d011418",
    "data": null
}

A successful example returned to the front-end:

{
    "code": 0,
    "flag": true,
    "desc": "success",
    "cause": null,
    "traceId": "07a3b99c-8cf8-45dc-a758-6c7636472cab",
    "data": {
        "count": 100,
        "name": "Zhang San"
    }
}

This is the article about SpringBoot project injecting traceId to track the entire requested log link. This is all about this article. For more related SpringBoot traceId log link content, please search for my previous article or continue browsing the related articles below. I hope everyone will support me in the future!