我正在开发一个 Reactive Spring Boot 应用程序,它使用 Log4j2 作为日志记录框架。默认情况下,我的应用程序在
INFO
级别进行日志记录,并且我在 application.yml
中设置日志记录级别
我希望能够在
DEBUG
级别记录仅针对一个特定请求,而无需全局更改日志记录级别或影响其他并发请求。例如,如果我为请求传递自定义标头(例如,X-Debug-Logging: true
),我希望该请求在 DEBUG
级别记录,但其他并行请求应继续在默认 INFO
级别记录。
我尝试过的: 我已经实现了一个 WebFilter 来检查 X-Debug-Logging 标头并调整日志记录级别,但我担心由于 Reactive Spring 异步处理请求,更改日志级别可能会影响同时处理的其他请求。
问题: 如何使用
Log4j2在 Reactive Spring 应用程序中以
DEBUG
级别动态记录单个请求,同时确保其他并发请求继续以默认 INFO
级别记录?
用例:
X-Debug-Logging: true
,则应记录在 DEBUG
。INFO
(默认)。DynamicThresholdFilter
或 ContextMapFilter
,它们允许您根据当前上下文数据过滤消息。
当过滤器用作全局过滤器时(即
<Configuration
> 的直接子级):
ACCEPT
将无条件接受该消息,NEUTRAL
的结果还将检查配置的记录器级别。(详情请参阅记录器阶段)。
所以你需要做的就是:
sampled
)并将其传播到所有线程,以便处理该请求。ACCEPT
,如果 sampled
为 true,则返回 NEUTRAL
。正如您所注意到的,传播价值可能是最困难的任务。为此,我建议您阅读Dariusz 关于上下文传播的博客系列。在这种特殊情况下,您需要:
io.micrometer:context-propagation
添加到您的应用程序中:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>context-propagation</artifactId>
</dependency>
main
方法中启用传播:
Hooks.enableAutomaticContextPropagation();
ThreadLocalAccessor
方法中为 Log4j ThreadContext
添加 main
。没有直接访问器,但 SLF4J MDC
桥接到 ThreadContext
:
ContextRegistry.getInstance().registerThreadLocalAccessor(new Slf4jThreadLocalAccessor());
WebFilter
,用于从线程上下文映射中设置和删除 sampled
键:
@Component
public class TracingFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
boolean sampled =
Boolean.parseBoolean(exchange.getRequest().getHeaders().getFirst("X-Debug-Logging"));
return chain.filter(exchange).contextWrite(c -> {
// Get a copy of the MDC map from the Reactor context
Map<String, Object> mdc =
new HashMap<>(c.getOrDefault(Slf4jThreadLocalAccessor.KEY, Collections.emptyMap()));
// Add or remove an entry
mdc.put("sampled", sampled ? "true" : null);
// Return a modified context
return c.put(Slf4jThreadLocalAccessor.KEY, Collections.unmodifiableMap(mdc));
});
}
}
DynamicThresholdFilter
,其中:
DEBUG
是 sampled
,,则对照
true
defaultThreshold
有任何其他非 sampled
值,则对照 null
检查消息,onMismatch
。<Configuration xmlns="https://logging.apache.org/xml/ns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
https://logging.apache.org/xml/ns
https://logging.apache.org/xml/ns/log4j-config-2.xsd">
<DynamicThresholdFilter key="sampled"
onMatch="ACCEPT"
onMismatch="NEUTRAL">
<KeyValuePair key="true" value="DEBUG"/>
</DynamicThresholdFilter>
<!-- Your `Appenders` and `Loggers` go here: -->
</Configuration>