Logback MDC put()可变对象

6
我正在使用Vaadin框架,它对拦截事件的支持很差,我无法知道何时会话或UI被激活,因此无法将它们的ID放入MDC中。通常我会:
public void onSessionBegin(){
    MDC.put("session", VaadinSession.getCurrent().toString()); //<-- String is immutable
}
public void onSessionEnd(){
    MDC.remove("session");
}

但是我没有这样的事件,所以我想要:
// in the servlet init or wherever
MDC.put("session", new Object(){
        public String toString() {
            VaadinSession.getCurrent().toString()
        };
    }); //<-- This is mutable and will be evaluated each time

无论会话更改多少次,我都能在日志中得到当前的会话。
这是可能的吗?我该如何用自定义实现替换logback MDC?我应该编辑slf4j和logback的源码吗?
1个回答

4
您不想为每个记录行从线程本地变量中检索当前会话(这就是VaadinSession.getCurrent()所做的)。API使用静态字符串类型,因为它是最快的。
实际上,Vaadin确实有SessionInitListenerSessionDestroyListener,但这也不是您想要的:MDC是线程本地的,但并不是在同一会话中处理的所有请求都在同一个线程中处理。因此,您必须在RequestHandler的实现中在每个请求中设置MDC中的值。我认为Vaadin没有用于请求结束的回调接口,因此似乎没有很好的清除该值的位置。
更新:在此答案被接受后,我发现实际上有一种更好的方法可以设置和清除该值,以便如果服务器为不同的会话重用线程,则不会包含错误信息。您应该子类化VaadinServletVaadinPortlet并覆盖createServletService()以返回VaadinServletServiceVaadinPortletService的自定义子类,该子类反过来分别覆盖requestStart()requestEnd()以设置和移除MDC中的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接