美文网首页
Sleuth链路添加额外传播字段

Sleuth链路添加额外传播字段

作者: 烂融小菜花 | 来源:发表于2019-11-27 12:01 被阅读0次

SpringCloud官网中关于Sleuth链路添加额外传播字段的描述如下:

有时需要传播额外的字段,例如请求 ID 或备用跟踪上下文。例如,如果你在 Cloud Foundry 环境中,可能希望传递请求 ID,如下例所示:

// when you initialize the builder, define the extra field you want to propagate
Tracing.newBuilder().propagationFactory(
  ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "x-vcap-request-id")
);

// later, you can tag that request ID or use it in log correlation
requestId = ExtraFieldPropagation.get("x-vcap-request-id");

即在初始化时,添加需要额外传播的字段。在之后需要用到的地方可以通过ExtraFieldPropagation.get("x-vcap-request-id")的方式来获取。

在具体项目中的用法:

我们公司的需求是:链路追踪不止可以记录后台微服务的的调用链,也要把前端用户的操作单元给记录下来。
实现方式:由前端传两个标识参数来记录用户操作的链路,在网关时,获取到传递过来的参数,然后通过Brave的额外传播字段进行链路捆绑,并在客户端(具体的微服务应用)进行配置,将 baggage 值设置为 Slf4j 的 MDC,然后即可在日志中输出该参数信息。

一.定义额外传播的字段:

在网关中定义传播的额外字段,经测试,有两种方式可以添加额外的字段

方式一:

@Configuration
@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER - 2)
public class SleuthPropagateConfig {

    /** 前端操作ID */
    public static final String OPERATION_ID = "X-Operation-ID";
    /** 前端操作名称 如:行政区划/保存 */
    public static final String OPERATION_NAME = "X-Operation-Name";

    @Bean
    public SleuthProperties sleuthProperties() {
        SleuthProperties sleuthProperties = new SleuthProperties();
        //会加baggage-前缀
//      List<String> dkBaggageKeys = new ArrayList<>();
//      dkBaggageKeys.add(OPERATION_ID);
//      List<String> baggageKeys = sleuthProperties.getBaggageKeys();
//      if (CollectionUtils.isEmpty(baggageKeys)) {
//          sleuthProperties.setBaggageKeys(dkBaggageKeys);
//          return sleuthProperties;
//      }
//      if (!baggageKeys.contains(OPERATION_ID)) {
//          sleuthProperties.getBaggageKeys().add(OPERATION_ID);
//      }
//      if (!baggageKeys.contains(OPERATION_NAME)) {
//          sleuthProperties.getBaggageKeys().add(OPERATION_NAME);
//      }
        
        //不会加前缀
        List<String> frontTraceKeys = new ArrayList<>();
        frontTraceKeys.add(OPERATION_ID);
        frontTraceKeys.add(OPERATION_NAME);
        List<String> propagationKeys = sleuthProperties.getPropagationKeys();
        if (CollectionUtils.isEmpty(propagationKeys)) {
            sleuthProperties.setPropagationKeys(frontTraceKeys);
            return sleuthProperties;
        }
        if (!propagationKeys.contains(OPERATION_ID)) {
            sleuthProperties.getPropagationKeys().add(OPERATION_ID);
        }
        if (!propagationKeys.contains(OPERATION_NAME)) {
            sleuthProperties.getPropagationKeys().add(OPERATION_NAME);
        }
        return sleuthProperties;
    }
}

但是这种方式不是很优雅,本人用的是第二种方式
方式二:

@Configuration
@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER - 2)
public class SleuthPropagateConfig {

    /** 前端操作ID */
    public static final String OPERATION_ID = "X-Operation-ID";
    /** 前端操作名称 如:行政区划/保存 */
    public static final String OPERATION_NAME = "X-Operation-Name";

    /**
     * 定义链路追踪额外传播字段
     * @return
     */
    @Bean
    public Tracing tracing() {
        return Tracing.newBuilder().propagationFactory(
                ExtraFieldPropagation.newFactoryBuilder(B3Propagation.FACTORY)
                        .addField(OPERATION_NAME)
                        .addField(OPERATION_ID)
                        //.addPrefixedFields("x-baggage-", Arrays.asList(OPERATION_NAME, OPERATION_ID))
                        .build()
        ).build();
    }
}

二.在网关过滤器中设置传播字段的信息

@Component
public class FrontTraceFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        String operationId = exchange.getRequest().getQueryParams().getFirst(SleuthPropagateConfig.OPERATION_ID);
        String operationName = exchange.getRequest().getQueryParams().getFirst(SleuthPropagateConfig.OPERATION_NAME);

        if (!StringUtils.isEmpty(operationId)
                && StringUtils.isEmpty(ExtraFieldPropagation.get(SleuthPropagateConfig.OPERATION_ID))) {
            ExtraFieldPropagation.set(SleuthPropagateConfig.OPERATION_ID, operationId);
        }
        if (!StringUtils.isEmpty(operationName)
                && StringUtils.isEmpty(ExtraFieldPropagation.get(SleuthPropagateConfig.OPERATION_NAME))) {
            ExtraFieldPropagation.set(SleuthPropagateConfig.OPERATION_NAME, operationName);
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

三.在客户端(微服务应用)添加配置

在application.yml中添加额外传播字段的相关配置,sleuth2.0后必须配置,否则在客户端获取不到字段信息

spring:
  application:
    name: demo-feign2
  sleuth:
    sampler:
      #调用链信息采样率
      probability: 1.0
    # 注意, Sleuth2.0.0之后, baggage的 key 必须在这里配置才能生效
#    baggage-keys:
#      - X-Operation-ID
#      - X-Operation-Name
    propagation-keys:
      - X-Operation-ID
      - X-Operation-Name
    log:
      slf4j:
        #自动额外传播字段设置为 Slf4j 的 MDC
        whitelisted-mdc-keys:
        - X-Operation-ID
        - X-Operation-Name

四.在客户端中使用额外的传播字段

ExtraFieldPropagation.get("key");

五.logback日志配置

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
    <springProperty scope="context" name="LOG_FILE" source="logging.path"/>
    <springProperty scope="context" name="ServerPort" source="server.port"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date [%thread] %-5level %logger{80} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="LOGSTASH" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_FILE}.json</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}/${APP_NAME}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <timestamp>
                    <timeZone>UTC</timeZone>
                </timestamp>
                <pattern>
                    <pattern>
                        {
                        "level": "%level",
                        "service": "${APP_NAME:-}",
                        "traceId": "%X{X-B3-TraceId:-}",
                        "spanId": "%X{X-B3-SpanId:-}",
                        "parentSpanId": "%X{X-B3-ParentSpanId:-}",
                        "exportable": "%X{X-Span-Export:-}",
                        "pid": "${PID:-}",
                        "thread": "%thread",
                        "class": "%logger{40}",
                        "method": "%M",
                        "line": "%L",
                        "message": "%message",
                        "operationId": "%X{X-Operation-ID}"
                        "operationName": "%X{X-Operation-Name}"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="LOGSTASH" />
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

六.logback日志输出结果

{"@timestamp":"2019-11-27T04:00:33.233+00:00","level":"INFO","service":"demo-feign2","traceId":"04f1bfb59beb7053","spanId":"c7ba04760057c6f2","parentSpanId":"04f1bfb59beb7053","exportable":"true","pid":"43252","thread":"http-nio-8302-exec-2","class":"com.caihua.demo.feign.web.HiController","method":"sayHi","line":"19","message":"this is feign2 controller, begin to call the feign service","operationId":"123","operationName":"save"}
{"@timestamp":"2019-11-27T04:00:33.243+00:00","level":"INFO","service":"demo-producer2","traceId":"04f1bfb59beb7053","spanId":"9ece8de790d6ad9e","parentSpanId":"c7ba04760057c6f2","exportable":"true","pid":"7968","thread":"http-nio-8301-exec-4","class":"com.caihua.demo.DemoProducer2Application","method":"home","line":"29","message":"this is producer controller, begin to call producer2 service ","operationId":"123","operationName":"save"}
{"@timestamp":"2019-11-27T04:00:33.244+00:00","level":"INFO","service":"demo-producer2","traceId":"04f1bfb59beb7053","spanId":"9ece8de790d6ad9e","parentSpanId":"c7ba04760057c6f2","exportable":"true","pid":"7968","thread":"http-nio-8301-exec-4","class":"com.caihua.demo.producer.HiService","method":"sayHi","line":"21","message":"this is producer2 HiService, i will call private method","operationId":"123","operationName":"save"}
{"@timestamp":"2019-11-27T04:00:33.244+00:00","level":"INFO","service":"demo-producer2","traceId":"04f1bfb59beb7053","spanId":"9ece8de790d6ad9e","parentSpanId":"c7ba04760057c6f2","exportable":"true","pid":"7968","thread":"http-nio-8301-exec-4","class":"com.caihua.demo.producer.HiService","method":"sayHello","line":"28","message":"hello: cai, this is private method","operationId":"123","operationName":"save"}

相关文章

网友评论

      本文标题:Sleuth链路添加额外传播字段

      本文链接:https://www.haomeiwen.com/subject/ayxpwctx.html