我正在使用Spring projectreactor reactor-core 3.1.8.RELEASE。我正在为我的微服务实现一个日志框架,以获得JSON审计日志,因此使用上下文来存储某些字段,例如userID,协作ID,组件名称以及请求生命周期中常见的少数其他字段。由于Threadlocal
不能用于反应服务来存储这些元素,因此我必须使用上下文。但是参考上下文显然非常困难。我可以通过doOnEach
函数调用来获取Signal的上下文及其相关内容。如果我使用doOnEach
,它将被调用所有信号类型,我无法隔离错误,成功等等。此外,如果两者之间发生错误,则无论如何都会调用所有后续doOnEach
,因此日志将以多个onError
日志类型重复执行。
关于如何在Spring reactor中获取对上下文对象的引用,文档非常有限。有关生成审计日志的更好方法的任何帮助,我们都非常感谢您提供了包含协作ID以及在函数调用和外部调用中存储和传播的其他请求特定ID的审计日志。
代码片段 - 在WebFilter中,我设置了几个键值对,如下所示 -
override fun filter(exchange: ServerWebExchange, filterChain: WebFilterChain): Mono<Void> {
// add the context variables at the end of the chain as the context moves from
// downstream to upstream.
return filterChain.filter(exchange)
.subscriberContext { context ->
var ctx = context.put(RestRequestInfo::class.java, restRequestInfo(exchange))
ctx = ctx.put(COLLABORATION_ID, UUID.randomUUID().toString())
ctx=ctx.put(COMPONENT_NAME, "sample-component-name")
ctx=ctx.put(USER_NAME, "POSTMAN")
ctx
}
}
然后我想在所有后续日志中使用上面添加的键值对,以便像Splunk这样的日志聚合器可以根据协作ID获取与此特定请求关联的所有JSON日志。现在,从上下文中获取值的唯一方法是通过doOnEach函数调用,我们获得SIgnal的句柄,通过它我们可以处理上下文。但是,无论每个函数调用是成功还是失败,所有doOnEach都会在每个事件中被调用
return Mono.just(request)
.doOnEach(**Code to log with context data**)
.map(RequestValidations::validateRequest)
.doOnEach(**Code to log with context data**)
.map(RequestValidations::buildRequest)
.map(RequestValidations::validateQueryParameters)
.doOnEach(**Code to log with context data**)
.flatMap(coverageSummariesGateway::getCoverageSummaries)
.doOnEach(**Code to log with context data**)
.map({ coverageSummaries ->
getCoverageSummariesResponse(coverageSummaries, serviceReferenceId) })
.doOnEach(**Code to log with context data**)
.flatMap(this::renderSuccess)
.doOnEach(**Code to log with context data**)
.doOnError { logger.info("ERROR OCCURRED") }
谢谢!
答案 0 :(得分:0)
您可以执行以下操作:
return Mono.just(request)
.doOnEach(**Code to log with context data**)
.flatMap( r -> withMDC(r, RequestValidations::validateRequest))
以下方法将填充映射诊断上下文(MDC),因此您可以在日志中自动使用它(取决于您的日志记录模式)。例如。 logback具有%X{traceId}
,其中traceId
是tracingContext
映射中的键。
public static <T, R> Mono<R> withMDC(T value, Function<T, Mono<R>> f) {
return Mono.subscriberContext()
.flatMap( ctx -> {
Optional<Map> tracingContext = ctx.getOrEmpty("tracing-context-key");
if (tracingContext.isPresent()) {
try {
MDC.setContextMap(tracingContext.get());
return f.apply(value);
} finally {
MDC.clear();
}
} else{
return f.apply(value);
}
});
}
它不是很好,希望它最终会被Logging框架改进并自动注入上下文。