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”映射诊断上下文(简称MDC)是一种用于区分来自不同来源的交错日志输出的工具。
log4j official API of Class MDC
官方文档这样解释:
The MDC class is similar to the NDC class except that it is based on a map instead of a stack. It provides mapped diagnostic contexts. A Mapped Diagnostic Context, or MDC in short, is an instrument for distinguishing interleaved log output from different sources. Log output is typically interleaved when a server handles multiple clients near-simultaneously.
它类似于NDC,只不过NDC是基于栈,而MDC是基于map的。
MDC是一个用来区分不同来源的交错的日志输出的工具。当一个服务器几乎同时处理多个客户端时,日志输出通常是交错的。

The MDC is managed on a per thread basis. A child thread automatically inherits a copy of the mapped diagnostic context of its parent. MDC基于每个线程进行管理。一个子线程自动继承一份来自它父类的MDC拷贝。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值