目录
1. MAVEN
1.1. spring-cloud-starter-sleuth:2.0.0.RELEASE
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-core</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-servlet</artifactId>
<version>5.1.0</version>
</dependency>
1.2. spring-cloud-starter-sleuth:3.0.0
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-instrumentation</artifactId>
<version>3.0.0</version>
</dependency>
2. 获取代码
2.1. spring-cloud-starter-sleuth:2.0.0.RELEASE
// ServletServerHttpRequest request
TraceContext traceContext = (TraceContext) request.getServletRequest().getAttribute(TraceContext.class.getName());
String traceId = traceContext.traceIdString();
// HttpServletRequest request
TraceContext traceContext = (TraceContext) request.getAttribute(TraceContext.class.getName());
String traceId = traceContext.traceIdString();
2.2. spring-cloud-starter-sleuth:3.0.0
// ServletServerHttpRequest request
TraceContext traceContext = (TraceContext) request.getServletRequest().getAttribute(TraceContext.class.getName());
String traceId = traceContext.traceId();
// HttpServletRequest request
TraceContext traceContext = (TraceContext) request.getAttribute(TraceContext.class.getName());
String traceId = traceContext.traceId();
3. 为何可以如此获取?
版本 | 所在 jar | 全路径 |
---|---|---|
spring-cloud-starter-sleuth:2.0.0.RELEASE | brave-instrumentation-servlet | brave.servlet.TracingFilter |
spring-cloud-starter-sleuth:3.0.0 | spring-cloud-sleuth-instrumentation | org.springframework.cloud.sleuth.instrument.web.servlet.TracingFilter |
public final class TracingFilter implements Filter {
final ServletRuntime servlet = ServletRuntime.get();
final CurrentTraceContext currentTraceContext;
final HttpServerHandler<HttpServerRequest, HttpServerResponse> handler;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = this.servlet.httpServletResponse(response);
TraceContext context = (TraceContext)request.getAttribute(TraceContext.class.getName());
if (context != null) {
CurrentTraceContext.Scope scope = this.currentTraceContext.maybeScope(context);
try {
chain.doFilter(request, response);
} finally {
scope.close();
}
} else {
Span span = this.handler.handleReceive(new HttpServletRequestWrapper(req));
request.setAttribute(SpanCustomizer.class.getName(), span.customizer());
// 赋值 traceId
request.setAttribute(TraceContext.class.getName(), span.context());
...
...
}
}
}
4. 实际项目中使用
package com.zxguan.springcloud2.user.config;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@Order(0)
@RestControllerAdvice
public class ApiResponseAdvice implements ResponseBodyAdvice {
/**
* 判断需要处理的情况
*
* @param methodParameter
* @param selectedHttpMessageConverter
*
* @return boolean true: false:
*/
@Override
public boolean supports(MethodParameter methodParameter, Class selectedHttpMessageConverter) {
//
return false;
}
/**
* 消息体返回前处理
*
* @param body 返回的消息体
* @param methodParameter 响应类型
* @param mediaType 请求的响应 contentType
* @param selectedHttpMessageConverter 执行序列化的转换器
* @param request
* @param response
*
* @return Object 返回的消息体
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class selectedHttpMessageConverter, ServerHttpRequest request, ServerHttpResponse response) {
// 此处可以统一添加 traceId 到响应中
return null;
}
}
5. 日志中打印 traceId
借助 MDC
机制, 实现 traceId
的打印
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{X-B3-TraceId} %X{X-B3-SpanId}</pattern>
6. 特别注意
MDC
设置 X-B3-TraceId
, 可以通过自定义过滤器提前到过滤器级别,但需要注意 过滤器顺序
,自定义过滤器需排在 TracingFilter
之后