Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logback MDC put() mutable object

I'm working with Vaadin framework, and it has poor support for intercepting events and I can't know when a session or a UI gets activated, so I can't put their ids in MDC.

Normally I would:

public void onSessionBegin(){
    MDC.put("session", VaadinSession.getCurrent().toString()); //<-- String is immutable
}
public void onSessionEnd(){
    MDC.remove("session");
}

But I don't have such events, so I'd like to :

// 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

This way, no matter how many time will change the session, in the log I'll get the current one.

Is this possible? How can I replace the logback MDC implementation with a custom one? Should I edit the sources of slf4j and logback?

like image 529
lelmarir Avatar asked Sep 20 '13 09:09

lelmarir


1 Answers

You don't want to retrieve the current session from the thread local variable for each logging line (which is what VaadinSession.getCurrent() does). The API uses a static String type as that is the fastest.

Vaadin actually does have SessionInitListener and SessionDestroyListener, but that is also not what you want: MDC is thread local, but not all requests within the same session are handled within the same thread. So you have to set the value in the MDC at each request in an implementation of RequestHandler. I don't think Vaadin has a callback interface for the end of a request, so it seems there's no good place to clear the value.

UPDATE: after this answer got accepted, I found out that there is in fact a better way to set and clear the value so that if the server recycles threads for different sessions, it doesn't contain false information. What you should do is subclass VaadinServlet or VaadinPortlet and override createServletService() to return a custom subclass of VaadinServletService or VaadinPortletService that in turn overrides both requestStart() and requestEnd() to respectively set and remove the values in the MDC.

like image 80
herman Avatar answered Nov 17 '22 08:11

herman