我正在尝试实现Reactor订户上下文(http://projectreactor.io/docs/core/release/reference/#context),以便可以将SLF4J MDC中的值传递到Flux中,然后在其中使用这些值进行记录。
我使用SubscriberContext()方法设置值,例如:
someFlux().subscriberContext(Context.of(MDC_ATTRIBUTE, MDC.get(MDC_ATTRIBUTE)));
我也可以访问链中的上下文。例如,使用flatMap:
.flatMap(r -> Mono.subscriberContext().map(ctx -> {
String name = ctx.getOrDefault(MDC_ATTRIBUTE_NAME, "NO CTX");
return r;
}))
doOnEach()
也可以工作:
.doOnEach(signal -> {
Context ctx = signal.getContext();
if (signal.isOnNext()) {
try (MDC.MDCCloseable closeable = MDC.putCloseable(MDC_ATTRIBUTE_NAME, ctx.getOrDefault(MDC_ATTRIBUTE_NAME, "MAAAAN"))) {
log.debug("FINISHED: {}", requestName);
}
}
})
只有一个问题。我想在doOnSubscribe
,doOnError
和doOnSuccess
中记录一些内容。虽然我可以使用doOnEach检查signal.isOnNext()
或signal.isOnComplete()
,但发现从未调用过signal.isOnSubscribe()
。
因此,问题是:我如何在doOnSubscribe()
中获取上下文,或者这根本不可能?
答案 0 :(得分:1)
有可能,但并非在100%的用例中,都有一些技巧:
Flux.just("foo")
.doOnSubscribe(sub -> {
Scannable actual = Scannable.from(sub).scan(Scannable.Attr.ACTUAL);
if (actual instanceof CoreSubscriber) {
Context context = ((CoreSubscriber) actual).currentContext();
System.out.println(context);
}
})
.map(v -> "value: " + v) //below or above doOnSubscribe is fine
.subscriberContext(Context.of("foo", "bar")) //MUST be below doOnSubscribe
.blockLast();