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

相關文章
相關標籤/搜索