Log4j 2 API

Event Logging

EventLogger 类为记录应用程序中发生的事件提供了一种简单的机制。尽管 EventLogger 可用作启动应由审核日志记录系统处理的事件的方式,但 EventLogger 本身并未实现审核日志记录系统所需的任何功能,例如保证交付。

在典型的 Web 应用程序中,建议使用 EventLogger 的方式是使用与请求的整个寿命相关的数据(例如用户的 ID,用户的 IP 地址,产品名称等)填充 ThreadContext Map。可以在 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”的 Logger。 EventLogger 使用默认的 OFF 记录级别来表示它不能被过滤。可以使用StructuredDataLayout格式化这些事件以进行打印。