You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot结合Zipkin:自定义Trace ID及特定请求日志配置咨询

Great questions! Let's tackle each one with practical examples you can implement right away.


Can You Customize Trace ID Generation in Spring Sleuth?

Absolutely. Spring Sleuth gives you full flexibility to override its default Trace ID generation logic. Here's how to roll your own:

  1. Implement the TraceIdGenerator interface
    Create a class that generates your preferred unique ID (just make sure it's globally unique to avoid trace collisions):

    import org.springframework.cloud.sleuth.api.TraceIdGenerator;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import java.util.UUID;
    
    @Configuration
    public class CustomTraceIdConfig {
    
        @Bean
        public TraceIdGenerator customTraceIdGenerator() {
            return () -> {
                // Example: Use UUID without hyphens (matches Sleuth's default 32-char hex format)
                return UUID.randomUUID().toString().replace("-", "");
                // You could also use a custom sequence or business-specific ID here
            };
        }
    }
    
  2. Key Notes

    • Stick to a format compatible with Zipkin (usually 32-character hex strings) to avoid compatibility issues.
    • Ensure your ID is unique across your entire distributed system—this is critical for accurate tracing.

How to Only Track Specific Requests (500 Errors or Slow Responses)

You have two main approaches here: customizing Sleuth's sampling logic (to control what gets sent to Zipkin) or filtering logs (to only record these requests in your logs).

Option 1: Custom Sampling for Zipkin Tracing

Sleuth's Sampler decides whether a request gets traced and sent to Zipkin. Build a custom sampler that only triggers for your target requests:

Step 1: Track Request Start Time

First, add an interceptor to capture when the request starts:

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class RequestTimingInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.setAttribute("REQUEST_START_TIME", System.currentTimeMillis());
        return true;
    }
}

Step 2: Register the Interceptor

Add it to your Spring MVC config:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private RequestTimingInterceptor timingInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(timingInterceptor);
    }
}

Step 3: Build the Custom Sampler

This sampler checks for 500 errors or slow responses (adjust the threshold to your needs):

import org.springframework.cloud.sleuth.api.Span;
import org.springframework.cloud.sleuth.api.Sampler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class TargetRequestSampler implements Sampler {

    // Define your response time threshold (e.g., 500ms)
    private static final long RESPONSE_TIME_THRESHOLD = 500;

    @Override
    public boolean isSampled(Span span) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) return false;
        
        HttpServletRequest request = attributes.getRequest();

        // Check if the request resulted in a 500 error
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode != null && statusCode == 500) {
            return true;
        }

        // Check if response time exceeds threshold
        Long startTime = (Long) request.getAttribute("REQUEST_START_TIME");
        if (startTime != null) {
            long responseTime = System.currentTimeMillis() - startTime;
            if (responseTime > RESPONSE_TIME_THRESHOLD) {
                return true;
            }
        }

        // Default: Skip tracing for other requests
        return false;
    }
}

Option 2: Filter Logs for Target Requests

If you want to only log these requests (not just skip Zipkin tracing), use a Logback TurboFilter:

Step 1: Add Filter to logback-spring.xml

<configuration>
    <!-- ... your existing log config ... -->
    <turboFilter class="ch.qos.logback.classic.turbo.TurboFilter">
        <Name>targetRequestLogFilter</Name>
        <filter class="com.yourpackage.CustomLogFilter"/>
    </turboFilter>
</configuration>

Step 2: Implement the Filter

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class CustomLogFilter extends TurboFilter {

    private static final long RESPONSE_TIME_THRESHOLD = 500;

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) return FilterReply.NEUTRAL;
        
        HttpServletRequest request = attributes.getRequest();

        // Allow logs for 500 errors
        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
        if (statusCode != null && statusCode == 500) {
            return FilterReply.ACCEPT;
        }

        // Allow logs for slow responses
        Long startTime = (Long) request.getAttribute("REQUEST_START_TIME");
        if (startTime != null) {
            long responseTime = System.currentTimeMillis() - startTime;
            if (responseTime > RESPONSE_TIME_THRESHOLD) {
                return FilterReply.ACCEPT;
            }
        }

        // Reject logs for all other requests
        return FilterReply.DENY;
    }
}

内容的提问来源于stack exchange,提问作者Ankit Bansal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:05:42