Sleuth链路添加额外传播字段

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"}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容