2.0.1 新特性介绍: 在日志中记录trace id

微服务架构下,需要部署大量的微服务实例,调用情况复杂,给问题定位带来了很大的麻烦。 通过调用链系统能够很好的解决日志追踪的问题, 但是对于日常的开发调试,部署调用链仍然显得复杂。 java-chassis 提供了一种简单的机制,允许业务在记录日志的时候,包含trace id。

在日志系统中记录 trace id

java-chassis 使用 MDC 的方式记录 trace id, 可以在 log4j2 或者 logback 中打印 trace id。 java-chassis 记录 trace id 增加 了 Marker , 开发者可以方便的将这类日志进行分类输出。

log4j2的配置如下:

  1. <Appenders>
  2. <Console name="Console" target="SYSTEM_OUT">
  3. <PatternLayout pattern="[%d][%t][%p][%c:%L][%X{SERVICECOMB_TRACE_ID}] %m%n"/>
  4. </Console>
  5. </Appenders>

结合 Marker, 将日志分类显示:

  1. <Appenders>
  2. <Console name="Console" target="SYSTEM_OUT">
  3. <MarkerFilter marker="SERVICECOMB_MARKER" onMatch="DENY" onMismatch="ACCEPT"/>
  4. <PatternLayout pattern="[%d][%t][%p][%c:%L] %m%n"/>
  5. </Console>
  6. <Console name="Console-Tracing" target="SYSTEM_OUT">
  7. <MarkerFilter marker="SERVICECOMB_MARKER" onMismatch="DENY" onMatch="ACCEPT"/>
  8. <PatternLayout pattern="[%d][%t][%p][%c:%L][%X{SERVICECOMB_TRACE_ID}] %m%n"/>
  9. </Console>
  10. </Appenders>

logback的配置如下:

  1. <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
  2. <encoder>
  3. <pattern>%d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n</pattern>
  4. </encoder>
  5. </appender>

结合 Marker, 可以将日志分类显示:

  1. <appender name="STDOUT-TRACING" class="ch.qos.logback.core.ConsoleAppender">
  2. <!-- If applicable, can use ch.qos.logback.classic.filter.MarkerFilter -->
  3. <filter class="org.apache.servicecomb.foundation.logback.MarkerFilter">
  4. <Marker>SERVICECOMB_MARKER</Marker>
  5. <OnMismatch>DENY</OnMismatch>
  6. <OnMatch>ACCEPT</OnMatch>
  7. </filter>
  8. <encoder>
  9. <pattern>%d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n</pattern>
  10. </encoder>
  11. </appender>

业务日志包含 trace id

  • 记录 access log

java-chassis 只有少量的日志包含 trace id,业务可以方便的在自己记录的日志中包含 trace id。 下面开发一个简单的 Handler, 记录服务端的 access log。

  1. public class AccessLogHandler implements Handler {
  2. private static final Logger LOGGER
  3. = LoggerFactory.getLogger(AccessLogHandler.class);
  4. @Override
  5. public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
  6. invocation.getTraceIdLogger().info(LOGGER, "request for operation {} begin", invocation.getInvocationQualifiedName());
  7. invocation.next((resp) -> {
  8. invocation.getTraceIdLogger().info(LOGGER, "request for operation {} end", invocation.getInvocationQualifiedName());
  9. asyncResp.complete(resp);
  10. });
  11. }
  12. }

配置 Handler

  1. <config>
  2. <handler id="custom-access-log"
  3. class="org.apache.servicecomb.demo.prefix.AccessLogHandler"/>
  4. </config>

启用 Handler

  1. servicecomb:
  2. handler:
  3. chain:
  4. Provider:
  5. default: custom-access-log
  • 业务日志

可以在业务实现中记录 trace id

  1. public class RegisterUrlPrefixEndpoint {
  2. private static final Logger LOGGER
  3. = LoggerFactory.getLogger(RegisterUrlPrefixEndpoint.class);
  4. @GetMapping(path = "/getName")
  5. public String getName(@RequestParam(name = "name") String name) {
  6. ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked.");
  7. return name;
  8. }
  9. }

增加了 access log 和业务日志后的效果如下:

  1. [5e72e39e55209533-1] - request for operation PRODUCER rest demo-register-url-prefix-server.RegisterUrlPrefixEndpoint.getName begin
  2. [5e72e39e55209533-1] - get name invoked.
  3. [5e72e39e55209533-1] - request for operation PRODUCER rest demo-register-url-prefix-server.RegisterUrlPrefixEndpoint.getName end