log4j 的一个实用工具类--NDC–可在每一个日志前自动加上一个tag--介绍

在现实的场景中常常有这样的需求,在纷繁的日志文件中,经过搜索某一个关键字(如订单号),能方便清晰的列出某一业务(如支付)的完整的处理流程。java

一个笨办法是在每一个日志中加上该关键字,以下所示:apache

logger.info("[{}] entering pay",orderId);
logger.info("[{}] check whether order is repeated ",orderId);
logger.info("[{}] save order to db",orderId);
logger.error("[{}]", orderId, e);
......

有没有更方便的方法知足这一业务要求呢? 而不用这么麻烦要在每一个日志中都要显式加上tag,所幸log4j自身就提供了这么一个方便易用的工具类--NDC。并发

只要在入口方法中设置tag,离开方法前remove便可。见以下示例代码:app

protected static final Logger logger = LoggerFactory
            .getLogger(NDCDemo.class);
    void test1(long orderId){ //入口方法
        NDC.push("["+orderId+"]"); //进入方法设置tag
        logger.info("entering test1"); //正常记录日志 无需显式添加tag
        test2();
        test3();
        test6();
        NDC.remove(); //离开方法删除tag
    }
    private void test6() {
        logger.info("entering test6");
    }
    private void test3() {
        logger.info("entering test3");
        test5();
    }
    private void test5() {
        logger.info("entering test5");
    }
    private void test2() {
        logger.info("entering test2");
        test4();
    }
    private void test4() {
        logger.info("entering test4");
    }
    public static void main(String[] args) {       
        NDCDemo app = new NDCDemo();
        app.test1(System.currentTimeMillis());
    }

以及日志输出,注意每一个日志信息前都有了上述代码所设置的tag。工具

[04 21:10:02,032 INFO ] [main] com.tcl.gateway.log4j.NDCDemo - [1428153002029]-entering test1
[04 21:10:02,035 INFO ] [main] com.tcl.gateway.log4j.NDCDemo - [1428153002029]-entering test2
[04 21:10:02,035 INFO ] [main] com.tcl.gateway.log4j.NDCDemo - [1428153002029]-entering test4
[04 21:10:02,035 INFO ] [main] com.tcl.gateway.log4j.NDCDemo - [1428153002029]-entering test3
[04 21:10:02,035 INFO ] [main] com.tcl.gateway.log4j.NDCDemo - [1428153002029]-entering test5
[04 21:10:02,035 INFO ] [main] com.tcl.gateway.log4j.NDCDemo - [1428153002029]-entering test6

同时配置文件中输出模板须要添加一个字符x(表示从NDC取消息)。以下所示:spa

<layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" 
                value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c - %x-%m%n" />
        </layout>

这样的话即便在多用户并发的状况下(如servlet和dubbo service)也容易根据某一关键字(如订单号、ip)来定位出完整的业务链。日志

另外除了NDC外还有一个工具类--MDC–也适用于这一场景,使用方式和NDC差很少,仍沿用上述示例,仅需部分改动:code

void test1(int orderId){
        MDC.put("orderId", "["+orderId+"]"); // NDC.push --> MDC.put(key , value)
        logger.info("entering test1");
        test2();
        test3();
        test6();
        MDC.remove("orderId"); //NDC.remove --> MDC.remove(key)
    }

配置文件的输出模板中加一个X,以下所示:orm

<layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" 
                value="[%d{dd HH:mm:ss,SSS\} %-5p] [%t] %c -%X{orderId}-%m%n" />
        </layout>

另外他们二者的区别及更多用法见各自的javadoc。xml

相关文章
相关标签/搜索