Spring Cloud Sleuth如何在Webflux中传播MDC上下文,以便其内容可以记录在不同的线程中?

tzdcorbm  于 2023-04-20  发布在  Spring
关注(0)|答案(4)|浏览(473)

我想知道Spring Cloud Sleuth如何在线程之间传播MDC上下文,使每个线程都可以使用MDC参数。
我读过这篇文章https://simonbasle.github.io/2018/02/contextual-logging-with-reactor-context-and-mdc/,它建议使用订阅者上下文在线程之间传播MDC状态。
我需要对一些请求头中的其他parars做一些类似的事情,所以我创建了将其放入当前线程的MDC中并将其存储在订阅者上下文中。然而,恢复执行的下一个线程没有它可用。不知何故,我应该在新线程中使用上下文中的值再次调用MDC,但是如何呢?

@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ReactiveRequestCorrelationFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String principal = exchange.getRequest().getHeaders().getFirst("principal-header");
        MDC.put("principal", principal);
        return chain.filter(exchange)
                .subscriberContext(Context.of("principal", principal))
                .doOnTerminate(MDC::clear);
    }

}

看看这个控制器Map:

@GetMapping(value = "/v1/departments", produces = MediaType.APPLICATION_JSON_VALUE)
    public Flux<Department> getDepartments() {
        log.info("getDepartaments");
        return webClient.get().uri("http://someService:8080/api/v1/departamentosFoo").retrieve().bodyToFlux(Departments.class)
                .doOnNext(dep -> log.info("found department {}", dep));
    }

它生成以下日志:

logging.pattern.console="%magenta([%thread]) [%X{traceId}] [%X{spanId}] [%X{principal}]  - %m%n"
[boundedElastic-2] [d0a916db8be0cbf7] [d0a916db8be0cbf7] []  - getDepartments
[boundedElastic-2] [d0a916db8be0cbf7] [fb2367685db70201] []  - found department Department(id=1, nombre=dep, fechaAlta=Fri Apr 24 14:16:20 CEST 2020, staff=1, tag=, empresa=true)
[reactor-http-nio-3] [d0a916db8be0cbf7] [d0a916db8be0cbf7] []  - found department Department(id=1, nombre=dep, fechaAlta=Fri Apr 24 14:16:20 CEST 2020, staff=1, tag=, empresa=true)

请求在reactor-http-nio线程中启动,然后切换到boundedElastic-2。正如您所看到的,显示了traceId和spanId值,但不是我放在过滤器中的值。Sleuth是如何将其上下文(traceId spanId)传播到其他线程中的?

0lvr5msh

0lvr5msh1#

2023年更新:发表了一个新的文章系列,内容是关于React式系统中上下文传播的当前状态:https://spring.io/blog/2023/03/28/context-propagation-with-project-reactor-1-the-basics
2021年更新:注意,这里有很多修改,请务必查看最新的实现,如下链接指向旧提交。

它们使用Reactor Context沿着Reactor Hooks。来自spring-cloud-sleuth的相关代码:link
一些可能有用的链接:

vc9ivgsu

vc9ivgsu2#

你不需要任何自定义来实现这个功能。传播自定义HTTP头所需的一切就是告诉Sleuth它们:

#The one is on by default
spring.sleuth.log.slf4j.enabled=true

spring.sleuth.propagation-keys=principal-header
spring.sleuth.log.slf4j.whitelisted-mdc-keys=principal-header

(我使用的是properties版本,但yaml也是一样)
然后在logback配置中使用

[%X{principal-header}]

就是这样!
N.B.我个人更喜欢从头文件名中删除-header位。

cqoc49vn

cqoc49vn3#

做了一些研究,马丁在他的回答中提供的信息,我得出了如下结论:
更新过滤器:

@Slf4j
@RequiredArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE + 6)
public class ReactiveRequestCorrelationFilter implements WebFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        return chain.filter(exchange)
                .doOnSubscribe(s -> {
                    String principal = exchange.getRequest().getHeaders().getFirst("principal-header");
                    ExtraFieldPropagation.set("principal", principal);
                });
    }

}

application.yml

spring:
  sleuth:
    log:
      slf4j:
        whitelisted-mdc-keys: principal
    baggage-keys: principal

有了这个,我的自定义字段开始显示在日志中,Sleuth负责设置它并从MDC中清除它:

[boundedElastic-2] [fadba73bf6447d02] [fadba73bf6447d02] [myprincipal] getDepartaments
nbewdwxp

nbewdwxp4#

在请求中添加自定义头,以便打印到日志中并进行传播,请按照2.2.6.RELEASE的步骤操作

例如,我的httpheader包含一个带有关键字'correlationID'的头,我希望它打印在日志中,还需要标记并传播给其他人,我不需要更新java代码中的任何内容。
application.yml

spring:
  application:
    name: my-app-api
  sleuth:
   propagation:
    tag:
      whitelisted-keys:
        - correlationID
    enabled: true
  baggage:
    correlation-enabled: true
    correlation-fields:
      - correlationID
    remote-fields:
      - correlationID
    tag-fields:       
      - correlationID
  trace-id128: true
  log:
    slf4j:
      enabled: true
logging:
  pattern:
    level: "%5p [${spring.zipkin.service.name:${spring.application.name:-}},%X{X-Span-Export:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{correlationID:-}]"
  level:
    org:
      springframework: info

确保日志模式更新为新值,以便在日志上打印。(请检查logging.pattern.level字段)

在请求标题中

correlationID : sample-correlation-Id-123

在日志中

2021-01-15 12:02:52.938  INFO [my-app-api,true,6001846c68912f933a714816b62e04a0,3a714816b62e04a0,sample-correlation-Id-123]

相关问题