Log4j 2 API
事件日志
EventLogger类提供一种简单的机制来记录应用程序中发生的事件。虽然EventLogger用于生成应该被审计日志系统处理的事件,但它自身并没有提供任何诸如审计日志系统所需的保证交付等特性。
在典型的Web应用中使用EventLogger的推荐方法是用整个生命周期相关的数据来填充ThreadContext Map,例如用户的ID、用户的IP地址、产品名称,等等。这在Servlet的Filter中很容易做到,ThreadContext Map也可以在request周期末尾被清理。当一个事件需要被记录发生时,一个StructuredDataMessage应该被创建并填充。然后调用EventLogger.logEvent(msg)方法,msg是一个StructuredDataMessage的引用。
import org.apache.logging.log4j.ThreadContext;
import org.apache.commons.lang.time.DateUtils;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.TimeZone;
public class RequestFilter implements Filter {
private FilterConfig filterConfig;
private static String TZ_NAME = "timezoneOffset";
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
/**
* 在每个请求中填充MDC的示例过滤器。
*/
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
ThreadContext.put("ipAddress", request.getRemoteAddr());
HttpSession session = request.getSession(false);
TimeZone timeZone = null;
if (session != null) {
// Something should set this after authentication completes
String loginId = (String)session.getAttribute("LoginId");
if (loginId != null) {
ThreadContext.put("loginId", loginId);
}
// This assumes there is some javascript on the user's page to create the cookie.
if (session.getAttribute(TZ_NAME) == null) {
if (request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (TZ_NAME.equals(cookie.getName())) {
int tzOffsetMinutes = Integer.parseInt(cookie.getValue());
timeZone = TimeZone.getTimeZone("GMT");
timeZone.setRawOffset((int)(tzOffsetMinutes * DateUtils.MILLIS_PER_MINUTE));
request.getSession().setAttribute(TZ_NAME, tzOffsetMinutes);
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
}
}
}
ThreadContext.put("hostname", servletRequest.getServerName());
ThreadContext.put("productName", filterConfig.getInitParameter("ProductName"));
Threadcontext.put("locale", servletRequest.getLocale().getDisplayName());
if (timeZone == null) {
timeZone = TimeZone.getDefault();
}
ThreadContext.put("timezone", timeZone.getDisplayName());
filterChain.doFilter(servletRequest, servletResponse);
ThreadContext.clear();
}
public void destroy() {
}
}
使用EventLogger的示例类:
import org.apache.logging.log4j.StructuredDataMessage;
import org.apache.logging.log4j.EventLogger;
import java.util.Date;
import java.util.UUID;
public class MyApp {
public String doFundsTransfer(Account toAccount, Account fromAccount, long amount) {
toAccount.deposit(amount);
fromAccount.withdraw(amount);
String confirm = UUID.randomUUID().toString();
StructuredDataMessage msg = new StructuredDataMessage(confirm, null, "transfer");
msg.put("toAccount", toAccount);
msg.put("fromAccount", fromAccount);
msg.put("amount", amount);
EventLogger.logEvent(msg);
return confirm;
}
}
EventLogger使用一个名为“EventLogger”的Logger。EventLogger默认使用OFF的日志级别以暗示它不会被过滤。这些事件可以使用StructuredDataLayout进行格式化打印。