我想知道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)传播到其他线程中的?
4条答案
按热度按时间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
一些可能有用的链接:
vc9ivgsu2#
你不需要任何自定义来实现这个功能。传播自定义HTTP头所需的一切就是告诉Sleuth它们:
(我使用的是properties版本,但yaml也是一样)
然后在logback配置中使用
就是这样!
N.B.我个人更喜欢从头文件名中删除
-header
位。cqoc49vn3#
做了一些研究,马丁在他的回答中提供的信息,我得出了如下结论:
更新过滤器:
application.yml
有了这个,我的自定义字段开始显示在日志中,Sleuth负责设置它并从MDC中清除它:
nbewdwxp4#
在请求中添加自定义头,以便打印到日志中并进行传播,请按照2.2.6.RELEASE的步骤操作
例如,我的httpheader包含一个带有关键字'correlationID'的头,我希望它打印在日志中,还需要标记并传播给其他人,我不需要更新java代码中的任何内容。
application.yml
确保日志模式更新为新值,以便在日志上打印。(请检查logging.pattern.level字段)
在请求标题中
在日志中