Sleuth输出TraceId

2019-11-25  本文已影响0人  huiwq1990

一、环境搭建

1.1包配置

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-sleuth</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

1.2日志配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration scanPeriod="60 seconds" debug="false">
    <!-- https://docs.spring.io/spring-boot/docs/current/reference/html/howto-logging.html -->

    <property name="CONSOLE_LOG_PATTERN"
              value="[%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %X{X-B3-TraceId} %X{traceId} %yellow(%X{X-B3-TraceId}),%green(%X{X-B3-SpanId}),%blue(%X{X-B3-ParentSpanId}) %yellow(%thread) %green(%logger) %msg%n"/>

    <include resource="org/springframework/boot/logging/logback/defaults.xml"/>

    <!--<include resource="org/springframework/boot/logging/logback/base.xml"/>-->
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
    </root>

</configuration>

二、实现分析

2.1 sleuth日志插件

org.springframework.cloud.sleuth.log.Slf4jCurrentTraceContext#newScope

  1. 获取父span设置的信息
    2)将当前span的信息设置到MDC中,如果当前span为空,需要从MDC中移除。
    3)当span close时,将MDC设置为父级span信息。
@Override public Scope newScope(@Nullable TraceContext currentSpan) {
        final String previousTraceId = MDC.get("traceId");
        final String previousParentId = MDC.get("parentId");
        final String previousSpanId = MDC.get("spanId");
        final String spanExportable = MDC.get("spanExportable");
        final String legacyPreviousTraceId = MDC.get(LEGACY_TRACE_ID_NAME);
        final String legacyPreviousParentId = MDC.get(LEGACY_PARENT_ID_NAME);
        final String legacyPreviousSpanId = MDC.get(LEGACY_SPAN_ID_NAME);
        final String legacySpanExportable = MDC.get(LEGACY_EXPORTABLE_NAME);

        if (currentSpan != null) {
            String traceIdString = currentSpan.traceIdString();
            MDC.put("traceId", traceIdString);
            MDC.put(LEGACY_TRACE_ID_NAME, traceIdString);
            String parentId = currentSpan.parentId() != null ?
                    HexCodec.toLowerHex(currentSpan.parentId()) :
                    null;
            replace("parentId", parentId);
            replace(LEGACY_PARENT_ID_NAME, parentId);
            String spanId = HexCodec.toLowerHex(currentSpan.spanId());
            MDC.put("spanId", spanId);
            MDC.put(LEGACY_SPAN_ID_NAME, spanId);

2.2 Logback获取MDC信息

Logback对象层级关系:Logger -> Appender -> Encoder -> PatternLayout,Layout中head定义了pattern的convert。

ch.qos.logback.core.OutputStreamAppender#subAppend

subAppend调用prepareForDeferredProcessing设置MDC。

    public void prepareForDeferredProcessing() {
        this.getFormattedMessage();
        this.getThreadName();
        // fixes http://jira.qos.ch/browse/LBCLASSIC-104
        this.getMDCPropertyMap();
    }

2.3 MDCConvert

%X{X-B3-TraceId}被定义为MDCConverter,它从MDC中获取信息。

 @Override
    public String convert(ILoggingEvent event) {
        Map<String, String> mdcPropertyMap = event.getMDCPropertyMap();

        if (mdcPropertyMap == null) {
            return defaultValue;
        }

        if (key == null) {
            return outputMDCForAllKeys(mdcPropertyMap);
        } else {

            String value = mdcPropertyMap.get(key);
            if (value != null) {
                return value;
            } else {
                return defaultValue;
            }
        }
    }
image.png
上一篇 下一篇

猜你喜欢

热点阅读