如何在普通的Spring微服务应用程序(非Spring Boot)中跟踪请求?

huangapple go评论61阅读模式
英文:

How to trace requests in normal Spring micro service app (non Spring boot)?

问题

如何在普通的Spring微服务应用程序(非Spring Boot)中跟踪请求?
我知道Spring Boot提供了Sleuth,但我想在非Spring Boot应用程序中进行类似的操作,这是一个普通的Spring应用程序。当请求通过不同的微服务时,我们想要对它们进行跟踪。

英文:

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.

答案1

得分: 1

  1. You need to configure the Spring app to use a logback.xml file for logging.

  2. Create an interceptor that would set additional MDC contexts as Sleuth does.

  3. 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 talks specifically about Spring Boot, but you can use the same approach in a 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.

英文:
  1. You need to configure the Spring app to use a logback.xml file for logging.
  2. Create an interceptor that would set additional MDC contexts as Sleuth does
  3. You need to pass the same additional MDC contexts to other services in HTTP headers.

Log back Configuration

&lt;configuration&gt;
      &lt;appender class=&quot;ch.qos.logback.core.ConsoleAppender&quot; name=&quot;STDOUT&quot;&gt;
        &lt;encoder&gt;
          &lt;pattern&gt;[%date{dd-MM-yyyy HH:mm:ss.SSS}]  [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %logger{36} - %msg%n&lt;/pattern&gt;
        &lt;/encoder&gt;
      &lt;/appender&gt;
      &lt;appender class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot; name=&quot;FILE&quot;&gt;
        &lt;encoder&gt;
          &lt;pattern&gt;[%date{dd-MM-yyyy HH:mm:ss.SSS}]  [%thread] %-5level %X{traceId:-} %X{spanId:-} ${PID:-} %logger{36} - %msg%n&lt;/pattern&gt;
        &lt;/encoder&gt;
        &lt;file&gt;log/app.log&lt;/file&gt;
        &lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&gt;
          &lt;fileNamePattern&gt;log/app.%d{yyyy-MM-dd-HH}.log&lt;/fileNamePattern&gt;
          &lt;maxHistory&gt;30&lt;/maxHistory&gt;
          &lt;totalSizeCap&gt;200MB&lt;/totalSizeCap&gt;
        &lt;/rollingPolicy&gt;
      &lt;/appender&gt;
    
      &lt;logger level=&quot;INFO&quot; name=&quot;root&quot;&gt;
        &lt;appender-ref ref=&quot;STDOUT&quot;/&gt;
      &lt;/logger&gt;
    &lt;/configuration&gt;

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(&quot;TRACE_ID&quot;);
    String spanId = request.getHeader(&quot;SPAN_ID&quot;);
    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(&quot;TRACE_ID&quot;, traceId);
    MDC.put(&quot;traceId&quot;, traceId);
    MDC.put(&quot;SPAN_ID&quot;, spanId);
    MDC.put(&quot;spanId&quot;, spanId);
    log.info(&quot;[preHandle] HTTP: {}, URL: {} &quot;, request.getMethod(), request.getRequestURI());
    return true;
  }

  @Override
  public void postHandle(
      HttpServletRequest request,
      HttpServletResponse response,
      Object handler,
      ModelAndView modelAndView)
      throws Exception {
    log.info(&quot;[postHandle] HTTP: {}, URL: {} &quot;, 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(&quot;TRACE_ID&quot;, MDC.get(&quot;TRACE_ID&quot;));
  headers.set(&quot;SPAN_ID&quot;, MDC.get(&quot;SPAN_ID&quot;));

  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&lt;String&gt; response =
      restTemplate.exchange(url, HttpMethod.GET, entity, String.class);

In this simple example, TRACE_ID and SPAN_ID headers have been set.

huangapple
  • 本文由 发表于 2020年5月29日 18:15:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/62083662.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定