问题描述
如何在普通 Spring 微服务应用(非 Spring 启动)中跟踪请求?我知道 Spring boot 会给 Sleuth,但我想为非 Spring boot 应用程序做类似的事情,它是一个普通的 Spring 应用程序.当请求通过不同的微服务时,我们要跟踪它们.
- 您需要将 Spring 应用程序配置为使用 logback.xml 文件进行日志记录.
- 创建一个拦截器,可以像 Sleuth 一样设置额外的 MDC 上下文
- 您需要将相同的附加 MDC 上下文传递给 HTTP 标头中的其他服务.
登录配置
<appender class="ch.qos.logback.core.ConsoleAppender" name="STDOUT"><编码器><pattern>[%date{dd-MM-yyyy HH:mm:ss.SSS}] [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %记录器{36} - %msg%n</pattern></编码器></appender><appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILE"><编码器><pattern>[%date{dd-MM-yyyy HH:mm:ss.SSS}] [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %记录器{36} - %msg%n</pattern></编码器><file>log/app.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><fileNamePattern>log/app.%d{yyyy-MM-dd-HH}.log</fileNamePattern><maxHistory>30</maxHistory><totalSizeCap>200MB</totalSizeCap></rollingPolicy></appender><logger level="INFO" name="root"><appender-ref ref="STDOUT"/></配置>设置用于跟踪的 MDC 上下文的拦截器.
@Slf4j公共类 LoggerInterceptor 实现了 HandlerInterceptor {@覆盖public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)抛出异常{String traceId = request.getHeader("TRACE_ID");String spanId = request.getHeader("SPAN_ID");如果(traceId == null){traceId = UUID.randomUUID().toString();}//您可以生成新的spanId 或使用相同的spanId如果(spanId == null){spanId = UUID.randomUUID().toString();}MDC.put("TRACE_ID", traceId);MDC.put("traceId", traceId);MDC.put("SPAN_ID", spanId);MDC.put("spanId", spanId);log.info("[preHandle] HTTP: {}, URL: {} ", request.getMethod(), request.getRequestURI());返回真;}@覆盖public void postHandle(HttpServletRequest 请求,HttpServletResponse 响应,对象处理程序,ModelAndView modelAndView)抛出异常{log.info("[postHandle] HTTP: {}, URL: {} ", request.getMethod(), request.getRequestURI());MDC.clear();}}
如果您想测量执行时间,请为其添加一个分析器.在 Profiling Spring Boot,它具体说明了 Spring boot,但您也可以在 Spring 应用程序中使用相同的方法.
如果您使用的是 RestTemplate,那么您可以设置这些标题.
HttpHeaders headers = new HttpHeaders();headers.set("TRACE_ID", MDC.get("TRACE_ID"));headers.set("SPAN_ID", MDC.get("SPAN_ID"));HttpEntity entity = new HttpEntity(headers);RestTemplate restTemplate = new RestTemplate();SimpleClientHttpRequestFactory rf =(SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();rf.setReadTimeout(2 * Constants.ONE_MILLI_INT);rf.setConnectTimeout(2 * Constants.ONE_MILLI_INT);ResponseEntity回应 =restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
在这个简单的例子中,TRACE_ID
和 SPAN_ID
标头已经设置.
How to trace requests in normal Spring micro service app (non Spring boot) ?I know Spring boot give Sleuth but I wanted to do the similar for non Spring boot app, its a normal Spring app. When request passes through the different micro-service, we want to trace them.
- You need to configure the Spring app to use a logback.xml file for logging.
- Create an interceptor that would set additional MDC contexts as Sleuth does
- You need to pass the same additional MDC contexts to other services in HTTP headers.
Log back Configuration
<configuration>
<appender class="ch.qos.logback.core.ConsoleAppender" name="STDOUT">
<encoder>
<pattern>[%date{dd-MM-yyyy HH:mm:ss.SSS}] [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender class="ch.qos.logback.core.rolling.RollingFileAppender" name="FILE">
<encoder>
<pattern>[%date{dd-MM-yyyy HH:mm:ss.SSS}] [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %logger{36} - %msg%n</pattern>
</encoder>
<file>log/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>log/app.%d{yyyy-MM-dd-HH}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>200MB</totalSizeCap>
</rollingPolicy>
</appender>
<logger level="INFO" name="root">
<appender-ref ref="STDOUT"/>
</logger>
</configuration>
Interceptor that sets the MDC context for tracing.
@Slf4j
public class LoggerInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String traceId = request.getHeader("TRACE_ID");
String spanId = request.getHeader("SPAN_ID");
if (traceId == null) {
traceId = UUID.randomUUID().toString();
}
// You can generate new spanId or use the same one
if (spanId == null) {
spanId = UUID.randomUUID().toString();
}
MDC.put("TRACE_ID", traceId);
MDC.put("traceId", traceId);
MDC.put("SPAN_ID", spanId);
MDC.put("spanId", spanId);
log.info("[preHandle] HTTP: {}, URL: {} ", request.getMethod(), request.getRequestURI());
return true;
}
@Override
public void postHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler,
ModelAndView modelAndView)
throws Exception {
log.info("[postHandle] HTTP: {}, URL: {} ", request.getMethod(), request.getRequestURI());
MDC.clear();
}
}
If you want to measure execution time then add a profiler for the same. Read more about the same at the example at Profiling Spring Boot, it says specific about Spring boot but you can use the same approach in Spring app as well.
If you're using RestTemplate then you can set these headers.
HttpHeaders headers = new HttpHeaders();
headers.set("TRACE_ID", MDC.get("TRACE_ID"));
headers.set("SPAN_ID", MDC.get("SPAN_ID"));
HttpEntity entity = new HttpEntity(headers);
RestTemplate restTemplate = new RestTemplate();
SimpleClientHttpRequestFactory rf =
(SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();
rf.setReadTimeout(2 * Constants.ONE_MILLI_INT);
rf.setConnectTimeout(2 * Constants.ONE_MILLI_INT);
ResponseEntity<String> response =
restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
In this simple example, TRACE_ID
and SPAN_ID
headers have been set.
这篇关于如何在普通 Spring 微服务应用程序(非 Spring 启动)中跟踪请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!