Log4j Java logging or Logback the NDC and MDC function

The difference between the NDC and MDC

Java implementation framework used in the log there are many commonly used and the java.util.logging log4j and logback, but is an open source log4j log component (Wrapped implementations) apache achieved, native slf4j logback is achieved (Native implementations). It should be noted slf4j Java is a simple log facade (The Simple Logging Facade for Java), if used logs slf4j facade, you must use to slf4j-api, but logback is straightforward to implement, so no other additional conversion and transition zone to consumption, and to call implementation slf4j log4j, it needs an adaptation layer, to achieve adaptation to the mode slf4j-api log4j of callable.

After finished basic difference logging framework, we look at the NDC and MDC.

Whether log4j or logback, print log to be able to reflect where the problem can quickly locate the crux of the problem, it is necessary to carry context information (context information), then the store two important classes of this information is NDC ( Nested Diagnostic Context) and MDC (Mapped Diagnositc Context).

NDC storing a context stack mechanism employed, the separate thread, the parent child threads from the thread context copy. Its call as follows:

1. Start calling
NDC.push (message);

2. Remove the top message
NDC.pop ();

3. Clear all the news, call must appear before the thread exits, otherwise it will lead to memory overflow.
NDC.remove ();

4. The output of the template, note the lowercase [% X]
log4j.appender.stdout.layout.ConversionPattern = [{D% the MM-dd-YYYY HH: mm: SSS}] [% X]:%% n-m

MDC using the stored context Map of independent threads, threads sub-copy from the parent thread context. Its call as follows:

1. The context information is saved to
MDC.put (key, value);

2. Get the information provided from the context
MDC.get (key);

3. context clearly specified key information
MDC.remove (key);

4. Clear All
clear ()

The output template, note the capital [% {X-Key}]
log4j.appender.consoleAppender.layout.ConversionPattern -4R% = [% T] 5P% C% X% -% m -% n-X-%} {Key

Finally, it should be noted that:

  • Use% X Map of all data
  • Use% X {key} Specifies the output value of the Map key
  • Use% x the entire contents of the Stack output

Examples of using MDC

//MdcUtils.java
// import ...MdcConstants // 这个就是定义一个常量的类,定义了SERVER、SESSION_ID等
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

public class MdcUtils {

    private final static Logger logger = LoggerFactory.getLogger(MdcUtils.class);

    private static void put(String key, Object value) {
        if (value != null) {
            String val = value.toString();
            if (StringUtils.isNoneBlank(key, val)) {
                MDC.put(key, val);
            }
        }
    }

    public static String getServer() {
        return MDC.get(MdcConstants.SERVER);
    }

    public static void putServer(String server) {
        put(MdcConstants.SERVER, server);
    }

    public static String getSessionId() {
        return MDC.get(MdcConstants.SESSION_ID);
    }

    public static void putSessionId(String sId) {
        put(MdcConstants.SESSION_ID, sId);
    }

    public static void clear() {
        MDC.clear();
        logger.debug("mdc clear done.");
    }
}

MdcConstants of the tool class is a constant defined class, defined SERVER, SESSION_ID the like, it is to put a call to put the method of the MDC slf4j. Other analogy.

Look at specific ways to use the tools of:

// MdcClearInterceptor.java
import ...MdcUtils; // 导入上面的工具类
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class MdcClearInterceptor extends HandlerInterceptorAdapter {
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler)
                    throws Exception {
        MdcUtils.clear();
    }
}

In the interceptor, rewrite afterConcurrentHandlingStarted method to perform a clear methodological tools category, that is to clear the log of this session context by calling slf4j a clear method. Why put afterConcurrentHandlingStarted approach it? This is probably realize springmvc was from the interceptor.

springmvc interception HandlerInterceptor interface defines three methods (code below), methods specifically described in the Notes:

public interface HandlerInterceptor {  
    //在控制器方法调用前执行
    //返回值为是否中断,true,表示继续执行(下一个拦截器或处理器)
    //false则会中断后续的所有操作,所以我们需要使用response来响应请求
    boolean preHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler)   
            throws Exception;  

    //在控制器方法调用后,解析视图前调用,我们可以对视图和模型做进一步渲染或修改
    void postHandle(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, ModelAndView modelAndView)   
            throws Exception;  
    //整个请求完成,即视图渲染结束后调用,这个时候可以做些资源清理工作,或日志记录等
    void afterCompletion(  
            HttpServletRequest request, HttpServletResponse response,   
            Object handler, Exception ex)  
            throws Exception;  
}  

Many times, we need only the above three methods is enough, because we only need to inherit HandlerInterceptorAdapterit, HandlerInterceptorAdapter indirectly to achieve the HandlerInterceptor interface and made empty implementation for the three methods HandlerInterceptor, and therefore more easily customize our own implementation.

HandlerInterceptor from respect, a more HandlerInterceptorAdapter implementation afterConcurrentHandlingStarted(), it HandlerInterceptorAdapter from direct implementation classes AsyncHandlerInterceptor, AsyncHandlerInterceptor HandlerInterceptor from the interface directly inherited, and added a new afterConcurrentHandlingStarted () method for processing asynchronous requests, there is a time when the Controller asynchronous request method will when the trigger method, asynchronous requests to support preHandle, then execute afterConcurrentHandlingStarted. Execution preHandle, postHandle, afterCompletion after the completion of the asynchronous thread.

As for those that might be used logs from the field where the assignment of it, is what to call MDCUtils.put () methods? Generally, we will achieve a RequestHandlerInterceptor, treatment can log fields in preHandler method. as follows:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
    if (DispatcherType.ASYNC.equals(request.getDispatcherType())) {
        return true;
    }
    
    // 开始保存信息到日志上下文
    MdcUtils.putServer(request.getServerName());
    String sId = request.getHeader(HeaderConstants.SESSION_ID);
    MdcUtils.putSessionId(sId);

    if (sessionWhiteList.contains(request.getPathInfo())) {
        return true;
    }

    // TODO 处理其他业务
}

Not finished, now see, we have two custom interceptor achieved. How to use, according to the log correct our will print it? Necessarily, the interceptor is in order, if a plurality of interceptors, the interceptor will form a chain, similar to the AOP execution sequence, first pre-defined first interception performed, the registration post and end intercepting interception (afterCompletion) after the execution.

Soga, we need to clear some useless information last request, once again our information is written to the MDC (interceptor configuration in the DispatcherServlet), due afterConcurrentHandlingStarted () method requires an asynchronous request triggers, so we need the web. xml configuration increases the DispatchServlet <async-supported>true</async-supported>configuration.

<mvc:interceptors>
    <bean class="com.xxx.handler.MdcClearInterceptor"/>
    <bean class="com.xxx.handler.RequestContextInterceptor"/>
</mvc:interceptors>

Or this:

<mvc:interceptors>
    <!-- 前置拦截器 -->
    <mvc:interceptor>
        <!-- 这里面还以增加一些拦截条件-->
        <!--<mvc:exclude-mapping path="/user/logout"/>-->
        <!-- 用户退出登录请求 -->
        <!-- <mvc:exclude-mapping path="/home/"/> -->
        <!--在home中定义了无须登录的方法请求,直接过滤拦截-->
        <!-- <mvc:mapping path="/**"/>-->
        <bean class="com.xxx.handler.MdcClearInterceptor"/>
    </mvc:interceptor>

    <!-- 后置拦截器 -->
    <mvc:interceptor>
        <bean class="com.xxx.handler.RequestContextInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

In this paper, starting "open-minded" personal blog, reproduced, please be sure before signature, reproduced, please indicate the source.

Ancient Masters of Tao, subtle Xuan Tong, deep unrecognizable. Fu Wei unrecognizable, so the receiving strong whom:
Yu Xi if winter Shibukawa, still fear neighbors if Xi, Xi Yan if its passengers, Huan Xi Ruo-Bing of release, which if Park London Xi, Xi which Ruogu Kuang, Xi mixed if its turbidity.
Practice makes cloud to tranquility Xu Qing? Practice makes it safe to move Xu Sheng?
Paul does not want this road surplus. Husband does not profit, it could become a new and spacious.

Please pay attention to my micro-channel public number: rain is like playing the piano , Thanks ♪ (· ω ·) Techno

Wechat QR code

Guess you like

Origin www.cnblogs.com/joyven/p/11776524.html