Как создать шаблон log4j с выводом значения метода?

У меня есть класс где храниться SessionId можно ли как нибудь настроить log4j.propirties, чтобы выводить автоматом в каждом логе SessionId ?
  • Вопрос задан
  • 268 просмотров
Пригласить эксперта
Ответы на вопрос 2
zolt85
@zolt85
Программист
Если мы сейчас говорим про web-приложение, то подобное можно провернуть при помощи javax.servlet.Filter.
Т.е. можем реализовать данный интерфейс, прописать нашу реализацию в web.xml, заставив перехватывать все запросы нашим фильтром.

Наш фильтр в методе doFilter дотягивается до класса, который знает про SessionId, и добавляет его [SessionId] к имени текущего треда (Thread.currentThread().setName(name);).

А в шаблоне log4j указать вывод имени треда через %t (PatternLayout)
Ответ написан
Комментировать
EugeneP2
@EugeneP2
Java Dev
Грубоватое решение, но тем не менее...

Для начало нужно создать реализацию ServletRequestListener, в котором мы будем получать id сессии и ассоциировать с потоком обрабатывающем текущий запрос с помощью 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) {	}
}


Листенер можно зарегистрировать или пометив его аннотацией @WebListener (для Servlet API 3.x), или по старинки, прописав его в web.xml

<listener>
        <listener-class>ua.home.web.listener.RequestListener</listener-class>
    </listener>


С помощью нашего статического метода ServletRequestListener.getCurrentSessionId() мы сможем получать id сессии вне сервлета.

Далее нам нужно переопределить метод format класса PatternLayout и прописать новую реализацию в log4j.properties.
В новой реализации метода, мы будет получать id сессии и заменять наш псевдопаттер в строке лога на 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

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


Теперь, если мы где то вызовем, например LOG.info("log message"), то в лог у нас запишется строка:

2016-08-23 12:20:18 TestServlet [INFO] 441135221F8A492364C836560BDEE15E log message
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы