Belongs to following categories: Integration, ULC5.2,
Purpose
Server-side applications are typically multi-threaded and therefore logging has to deal with these parallel execution paths. In the case of ULC, logging output should be clearly related to the originating session.
This contribution demonstrates how to include session identifying information in Log4J's logging output using the MDC (Mapped Diagnostic Context) feature. It also shows how one can execute code just before or after ULC processes a request.
Resources
Related To
How to use
Include the Log4J library and the
MDCSessionRegistry class with your (server-side) application code.
Register the
MDCSessionRegistry as shown below. This needs to be done prior to creating the first session. For this purpose, just create a static initializer in your main class which contains these two statements:
ICurrentSessionRegistry registry = new MDCSessionRegistry();
ULCSession.setCurrentSessionRegistry(registry);
You can now add logging statements to your code in the Log4J fashion. In order to distinguish between different sessions, a pattern has to be specified in the Log4J configuration which includes the session id and client IP-address. e.g.
<appender name="FileAppender" class="org.apache.log4j.FileAppender">
<param name="File" value="SomeLogFile.txt"></param>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %3X{MDC_SESSION_ID} / %X{MDC_SESSION_IP} %p %l - %m%n"/>
</layout>
</appender>
How it is implemented
The implementation uses Log4J's Mapped Diagnostic Context. The MDC binds logging information to a thread. Your task is to associate the thread with a ULC session. This is accomplished by means of the
MDCSessionRegistry class.
The class
MDCSessionRegistry creates the session-thread binding for Log4J. The method
setCurrentSession() is called before a request is processed by ULC on the server. This is the right spot to create Log4J MDC entries with key "MDC_SESSION_ID" and session id as value and with key "MDC_SESSION_IP" and client IP-address as value. At the end of request processing, the method
setCurrentSession() is called again with a null parameter. This time the Log4J MDC entries are removed.
public class MDCSessionRegistry implements ICurrentSessionRegistry
{
private static final ThreadLocal CURRENT_SESSION = new ThreadLocal(); public ULCSession getCurrentSession()
{
return (ULCSession) CURRENT_SESSION.get();
} public void setCurrentSession(ULCSession ulcSession)
{
CURRENT_SESSION.set(ulcSession);
handleMDC(ulcSession);
} private void handleMDC(ULCSession ulcSession)
{
if(ulcSession != null)
{
MDC.put("MDC_SESSION_ID", getSessionInfo().getSessionID());
MDC.put("MDC_SESSION_IP", getSessionInfo().getSessionIP());
}
else
{
MDC.remove("MDC_SESSION_ID");
MDC.remove("MDC_SESSION_IP");
}
} …
}The classes
SessionID and
SessionIP hold the session- and client-specific information that you would like to add to a log statement. This contribution simply holds the IP-address of the client which is fetched lazily using the
ClientContext. In addition, an incrementing number is assigned in order to distinguish different sessions associated with the same IP address.
Compatibility
The described functionality has been developed and tested using JDK 1.3.1_10 and ULC 5.2.
Author
bruno