Log4j 2 API
事件日志记录
EventLogger 类提供了一种简单的机制来记录应用程序中发生的事件。虽然 EventLogger 作为一种启动应由审计日志记录系统处理的事件的方式很有用,但它本身并没有实现审计日志记录系统所需的任何功能,例如保证交付。
在典型的 Web 应用程序中使用 EventLogger 的推荐方法是在 ThreadContext Map 中填充与请求整个生命周期相关的数据,例如用户的 ID、用户的 IP 地址、产品名称等。这可以在 servlet 过滤器中轻松完成,在 servlet 过滤器中,ThreadContext Map 也可以在请求结束时清除。当需要记录的事件发生时,应该创建一个 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;
}
/**
* Sample filter that populates the MDC on every request.
*/
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”的记录器。EventLogger 使用 OFF 作为默认日志级别,表示它不能被过滤。这些事件可以使用 StructuredDataLayout 格式化以进行打印。


