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

results matching ""

    No results matching ""