K
K
kirawa2016-08-22 13:59:50
Java
kirawa, 2016-08-22 13:59:50

How to create a log4j template with method value output?

I have a class where the SessionId is stored, is it possible to somehow configure log4j.propirties to display automatically in each SessionId log?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
E
Eugene, 2016-08-23
@zolt85

If we are now talking about a web application, then this can be done using javax.servlet.Filter .
Those. we can implement this interface, write our implementation in web.xml, forcing our filter to intercept all requests.
Our filter in the doFilter method reaches the class that knows about the SessionId and adds [SessionId] to the name of the current thread (Thread.currentThread().setName(name);).
And in the log4j template, specify the output of the thread name through %t ( PatternLayout )

E
Evhen, 2016-08-23
@EugeneP2

A crude solution, but nonetheless... First, we
need to create an implementation of ServletRequestListener , in which we will receive the session id and associate it with the thread processing the current request using ThreadLocal .

package ua.home.web.listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;


public class RequestListener implements ServletRequestListener {

  private static final ThreadLocal<String> sessionIds = new ThreadLocal<>();

  public static String getCurrentSessionId() {
    return 	sessionIds.get();
  }

  @Override
  public void requestInitialized(ServletRequestEvent servletRequestEvent) {
    HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();

    String id = request.getSession().getId();

    sessionIds.set(id);
  }

  @Override
  public void requestDestroyed(ServletRequestEvent servletRequestEvent) {	}
}

The listener can be registered either by annotating it with the @WebListener annotation (for Servlet API 3.x ), or the old-fashioned way by writing it in web.xml
<listener>
        <listener-class>ua.home.web.listener.RequestListener</listener-class>
    </listener>

With our static method ServletRequestListener.getCurrentSessionId(), we can get the session id outside of the servlet.
Next, we need to override the format method of the PatternLayout class and write a new implementation in log4j.properties .
In the new implementation of the method, we will get the session id and replace our pseudo-patter in the log line with the id.
package ua.home.web.log;

import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
import ua.home.web.listener.RequestListener;

public class CustomPatternLayout extends PatternLayout {
  @Override
  public String format(LoggingEvent event) {
    return  super.format(event).replace("%sid", RequestListener.getCurrentSessionId());
  }
}

log4j.properties file
log4j.rootCategory=INFO,S
log4j.appender.S=org.apache.log4j.ConsoleAppender
log4j.appender.S.layout=ua.home.web.log.CustomPatternLayout
log4j.appender.S.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %c{1} [%p] %sid %m%n

Now, if we call somewhere, for example LOG.info("log message"), then the line will be written to the log:
2016-08-23 12:20:18 TestServlet [INFO] 441135221F8A492364C836560BDEE15E log message

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question