应用日志打印 traceId 和 spanId

更新时间: 2019-07-01

SLF4J 提供了 MDC (Mapped Diagnostic Contexts)功能,可以支持用户定义和修改日志的输出格式以及内容。本文将介绍 SOFATracer 集成的 SLF4J MDC功能,方便用户在只简单修改日志配置文件的前提下输出当前 SOFATracer 上下文 TraceId 以及 SpanId

使用前提

为了在应用中的日志正确打印 TraceIdSpanId 参数,我们的日志编程接口需要面向 SLF4J 进行编程,即打印日志的编程接口不要依赖具体的日志实现。

  1. <dependency>
  2. <groupId>org.slf4j</groupId>
  3. <artifactId>slf4j-api</artifactId>
  4. </dependency>

引入依赖

如果是 SOFABoot 或者 Spring Boot 的应用具体的日志实现需要大家去引入,我们推荐的日志打印实现是 Logback 和 Log4j2,不推荐 Log4j,同时日志实现建议只使用一个而不要使用多个实现。

  • Logback 实现引入:
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-logging</artifactId>
  4. </dependency>
  • Log4j2 实现引入:
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-log4j2</artifactId>
  4. <!--SOFABoot 没有管控 log4j2 版本 -->
  5. <version>1.4.2.RELEASE</version>
  6. </dependency>

配置方法

我们基于 SLF4J MDC 的原理打印对应的 TraceId 和 SpanId,首先我们的应用中的日志编程接口应该面向 SLF4J,如通过如下的方式:

//引入接口
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//构造日志打印实例
private static final Logger logger = LoggerFactory.getLogger(XXX.class);

其次,我们为了正确打印 TraceIdSpanId 参数,我们还需要在日志的配置文件中配置 PatternLayout 的额外参数,这两个参数是 %X{SOFA-TraceId}%X{SOFA-SpanId},参数值我们均是从 MDC 中获取的值。

Logback 为例配置的 pattern 参数

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p  [%X{SOFA-TraceId},
%X{SOFA-SpanId}] 
---- %m%n</pattern>
  • 关键配置项目:[%X{SOFA-TraceId},%X{SOFA-SpanId}] 作为 Logback pattern 的一部分,在对应的 appender 被调用的时候,会根据 pattern 中的占位符替换为当前线程上下文中 TraceId 和 SpanId 的具体值,当前线程中没有对应的 TraceId 和 SpanId 值时,会用“空字符串”替代。Log4j2 配置 PatternLayout 样例
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p 
[%X{SOFA-TraceId},%X{SOFA-SpanId}] ---- %m%n " />

Log4j 配置 PatternLayout 样例

 <layout class="org.apache.log4j.PatternLayout">
     <param name="ConversionPattern" value="%d %-5p %-32t 
     [%X{SOFA-TraceId},%X{SOFA-SpanId}] - %m%n"/>
 </layout>

需要注意的是:[%X{SOFA-TraceId},%X{SOFA-SpanId}] 使我们推荐的打印格式,用户可以根据自己的实际需求场景进行定制

附:基于 Logback 示例工程的源代码地址