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 格式化以进行打印。