Apache Log4j2 API官方使用指南(四) —— EventLogger

什么是EventLogger

The EventLogger class provides a simple mechanism for logging events that occur in an application. While the EventLogger is useful as a way of initiating events that should be processed by an audit Logging system, by itself it does not implement any of the features an audit logging system would require such as guaranteed delivery.
EventLogger类提供了一种用于记录应用程序中发生的日志事件的简单机制。
尽管EventLogger作为一种启动事件的有效方法,(这种启动方法)应该被审核日志记录系统处理。但EventLogger本身并未实现审核日志记录系统所需的任何功能,例如保证交付。

EventLogger的使用

The recommended way of using the EventLogger in a typical web application is to populate the ThreadContext Map with data that is related to the entire lifespan of the request such as the user’s id, the user’s IP address, the product name, etc. This can easily be done in a servlet filter where the ThreadContext Map can also be cleared at the end of the request. When an event that needs to be recorded occurs a StructuredDataMessage should be created and populated. Then call EventLogger.logEvent(msg) where msg is a reference to the StructuredDataMessage.
在典型的Web应用程序中,使用EventLogger的推荐方法是,

  1. 用与请求的整个生命周期相关的数据(例如用户的ID,用户的IP地址,产品名称等)去填充ThreadContext Map。以上这些可以在一个Servlet过滤器中轻松做到,在该过滤器中,ThreadContext Map也可以在请求结束时被清除。
  2. 当需要记录的事件发生时,应创建并填充一个StructuredDataMessage对象。
  3. 然后调用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.
     * 在每次请求都填充MDC的过滤器示例
     * 什么是MDC在文末会提到
     */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        //在ThreadContext中填充相关数据,这边是IP地址
        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. 这里假设有一些js在用户页面上用来创建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() {
    }
}

Sample class that uses EventLogger. 使用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对象。
        StructuredDataMessage msg = new StructuredDataMessage(confirm, null, "transfer");
        msg.put("toAccount", toAccount);
        msg.put("fromAccount", fromAccount);
        msg.put("amount", amount);
        //最后调用EventLogger的logEvent方法来记录日志。
        EventLogger.logEvent(msg);
        return confirm;
    }
}

EventLogger日志的格式化和打印

The EventLogger class uses a Logger named “EventLogger”. EventLogger uses a logging level of OFF as the default to indicate that it cannot be filtered. These events can be formatted for printing using the StructuredDataLayout.
EventLogger使用OFF作为默认的日志级别来表示它不能被过滤。
这些日志事件可以使用StructuredDataLayout 格式化之后打印。

What is MDC filter?

“Mapped Diagnostic Context” is essentially a map maintained by the logging framework where the application code provides key-value pairs which can then be inserted by the logging framework in log messages. MDC data can also be highly helpful in filtering messages or triggering certain actions.
“映射的诊断上下文”实质上是由日志记录框架维护的映射,其中应用程序代码提供键值对,然后可以由日志记录框架将其插入日志消息中。
MDC数据在筛选消息或触发某些操作方面也可能非常有帮助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章