Closed bwzhang2011 closed 9 years ago
LOG4J(2)
的集成 想法不错,我理解和思考一下你说的实现过程。
另外,在MDC
的需求说明中,关于日志场景的说明还是比较模糊的,你能给一下更明确实际些的场景说明不?这样做起来更有目标感 :smile_cat: @bwzhang2011
@oldratlee 感谢回复。
使用MDC
是用来记录跟应用上下文环境中需要保存的一些数据,比如请求类提取的、跟执行有关的跟踪信息还有当异常发生的时候提取的,这些可以在appender
中的layout
来指定这些信息(比如%X{key1}: %X{key2}
等)。
一般场景可以是:
filter
类中写入parent thread
的内容(MDC.put
)——带有一traceId
或其余标记信息(用户)MDC.put
)——可提取跟traceId
或标记有关的信息(提取),并保存其余的消息(跟本线程有关的)并进行保存保存filter
的线程变量,finally { ThreadContext.clearAll() }
MtContextThreadLocal
新加上callback
方法:
protected void beforeExecute() {
}
protected void afterExecute() {
}
可以覆盖这个方法 来完成 log4j2
的设置,达到filter
的效果:
static MtContextThreadLocal<Map<String, String>> mtc = new MtContextThreadLocal<Map<String, String>>() {
@Override
protected void beforeExecute() {
final Map<String, String> log4j2Context = get();
for (Map.Entry<String, String> entry : log4j2Context.entrySet()) {
ThreadContext.put(entry.getKey(), entry.getValue());
}
}
@Override
protected void afterExecute() {
ThreadContext.clearAll();
}
@Override
protected Map<String, String> initialValue() {
return new HashMap<String, String>();
}
};
Log的代码:
public static void main(String[] args) throws Exception {
// Init Log Context, set MTC
// More KV if needed
final String TRACE_ID = "trace-id";
final String TRACE_ID_VALUE = "XXX-YYY-ZZZ";
ThreadContext.put(TRACE_ID, TRACE_ID_VALUE);
mtc.get().put(TRACE_ID, TRACE_ID_VALUE);
// Log in Main Thread
logger.info("Log in main!");
// Run task in thread pool
final ExecutorService executorService = Executors.newFixedThreadPool(1);
final Runnable task = new Runnable() {
@Override
public void run() {
// Log in thread pool
logger.info("Log in Runnable!");
}
};
final Future<?> submit = executorService.submit(MtContextRunnable.get(task));
submit.get();
executorService.shutdown();
}
完整示例:Log4j2ContextFilter.java 、 log4j2.xml
输出:
22:50:52.823 [main] INFO log4j2.Log4j2ContextFilter XXX-YYY-ZZZ - Log in main!
22:50:52.826 [pool-2-thread-1] INFO log4j2.Log4j2ContextFilter XXX-YYY-ZZZ - Log in Runnable!
@bwzhang2011 看看这样是不是可以解决你的问题了? 如果OK,我就发一个新版本,加上这个功能。
@oldratlee, 我再仔细看一下,看是否能合到工程中。T.K.S
@oldratlee SL4J
中MDC
类依赖于MDCAdapter
,个人感觉如果集成则需要提供一个针对其的实现。这样我仍然只需要操作MDC
即可。
相关的 SL4J
的MDC
和 multiple-thread-context
的集成,涉及如果设置业务的Log Context
如trace-id
,这个需要业务来完成, multi-thread-context
提供能力。
个人感觉如果集成则需要提供一个针对其的实现
你说能一下 『针对其的实现』如何做,给一下示例代码?
如果你比较清楚了,能直接实现一下,给个PullRequest
吗? :smile_cat: @bwzhang2011
很赞
赞
PS: 已提供集成库:
<dependency>
<groupId>com.ofpay</groupId>
<artifactId>logback-mdc-ttl</artifactId>
<version>1.4.0</version>
</dependency>
Hi~
注意到
multiple-thread-context
提供了上下文线程变量的传递,并提供了针对Runnable
及Callable
的支持。由于上述场景中有一部分是用在日志中,当前log4j(2)
提供了MDC
的支持。想问的是,能否提供一个针对其的增强支持,以
log4j2
为例已经提供了入口操作的类ThreadContext
,若在Executor
中传递则需要 使用 该类中的getContext()
andcloneStack()
方法。此外,框架是否考虑了如何清除这些线程安全变量(以
WEB
为例大多数是在filter
里面使用PUT
然后 执行完毕后POP
或CLEAR
)——是否有好的建议(以multi-thread-context
的使用为例)。