返回
Java Logback StructuredTaskScope 中跨分支 MDC 传播策略
java
2024-03-18 17:48:50
Logback 中 StructuredTaskScope 内的分支间 MDC 传播
问题
在 Java 21 及更高版本中,如果我们使用 StructuredTaskScope
创建多个分支任务,希望 MDC 值可以传播到这些分支中,以便所有日志都可以正确关联。
解决方法
目前,Logback 没有直接的方法来继承 MDC。以下是一些可能的解决方案:
1. 使用 ScopedValue
ScopedValue
值会被范围的分支继承,但需要直接访问 Logback 的内部组件或操作 MDC,这目前是不可行的。
2. 覆盖 MDCAdapter
覆盖 MDCAdapter
也失败了,因为 Logback 似乎没有使用它来读取 MDC 值。
潜在解决方案
一种可能的解决方案是将 MDC 值存储在 StructuredTaskScope
中,并在创建新分支时将它们传递下去。这可以通过以下步骤实现:
- 在
StructuredTaskScope
中创建MDCValues
类来存储 MDC 值。 - 在
fork()
方法中,创建新的MDCValues
实例并将当前 MDC 值复制到其中。 - 在新分支中,将
MDCValues
实例添加到当前ThreadLocal
上下文中。 - 在分支任务完成时,将
MDCValues
实例从ThreadLocal
上下文中删除。
代码示例
public class StructuredTaskScopeWithMDC {
public static void main(String[] args) {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// 设置 MDC 值
MDC.put("user", "John Doe");
MDC.put("order", "12345");
Supplier<String> user = scope.fork(() -> {
// 访问 MDC 值
String user = MDC.get("user");
// 记录日志
logger.info("User: " + user);
return user;
});
Supplier<Integer> order = scope.fork(() -> {
// 访问 MDC 值
Integer order = Integer.parseInt(MDC.get("order"));
// 记录日志
logger.info("Order: " + order);
return order;
});
scope.join().throwIfFailed();
// 记录日志
logger.info("User: " + user.get());
logger.info("Order: " + order.get());
}
}
}
结论
通过将 MDC 值存储在 StructuredTaskScope
中,我们可以在分支任务之间传播这些值。这确保了所有日志都可以正确关联。
常见问题解答
- 我可以在 Logback 中直接访问内部组件吗?
不,目前没有公开的方法来直接访问 Logback 的内部组件。
- 我可以覆盖 MDCAdapter 吗?
覆盖 MDCAdapter
也无效,因为 Logback 似乎没有使用它来读取 MDC 值。
- 这个解决方案适用于所有 MDC 键吗?
是的,此解决方案适用于所有 MDC 键,包括来自第三方库的键。
- 这个解决方案会影响 Logback 的性能吗?
该解决方案对 Logback 的性能影响很小。在大多数情况下,它不会造成明显的开销。
- 这个解决方案适用于所有版本的 Logback 吗?
此解决方案适用于 Logback 1.4 及更高版本。