在
多用戶(hù)并發(fā)的環(huán)境下,通常是由不同的線(xiàn)程分別處理不同的客戶(hù)端請(qǐng)求。此時(shí)要在日志信息中區(qū)分出不同的客戶(hù)端,你可以為每一個(gè)線(xiàn)程生成一個(gè)Logger,從
而從一堆日志信息中區(qū)分出哪些信息是屬于哪個(gè)線(xiàn)程的,但這種方式并不高效。Log4J巧妙地使用了Neil
Harrison提出的“NDC(嵌套診斷環(huán)境)”機(jī)制來(lái)解決這個(gè)問(wèn)題。Log4J為同一類(lèi)別的線(xiàn)程生成一個(gè)Logger,多個(gè)線(xiàn)程共享使用,而它僅在日
志信息中添加能夠區(qū)分不同線(xiàn)程的信息。NDC是什么?舉例來(lái)說(shuō),如果一個(gè)Servlet接到并發(fā)請(qǐng)求時(shí),為每一個(gè)客戶(hù)端創(chuàng)建一個(gè)新的線(xiàn)程,然后分配一個(gè)用
于保存該請(qǐng)求上下文的NDC堆棧。該上下文可能是發(fā)出請(qǐng)求的主機(jī)名、IP地址或其它任何可以用于標(biāo)識(shí)該請(qǐng)求的信息。這樣,由于不同的客戶(hù)端處理線(xiàn)程具有不
同的NDC堆棧,即使這個(gè)Servlet同時(shí)生成多個(gè)線(xiàn)程處理不同的請(qǐng)求,這些日志信息仍然可以區(qū)分出來(lái),就好像Log4J為每一個(gè)線(xiàn)程都單獨(dú)生成了一個(gè)
Logger實(shí)例一樣。在Log4J中是通過(guò)org.apache.log4j.NDC實(shí)現(xiàn)這種機(jī)制的。使用NDC的方法也很簡(jiǎn)單,步驟如下:
1. 在進(jìn)入一個(gè)環(huán)境時(shí)調(diào)用NDC.push(String),然后創(chuàng)建一個(gè)NDC;
2. 所做的日志操作輸出中包括了NDC的信息;
3. 離開(kāi)該環(huán)境時(shí)調(diào)用NDC.pop方法;
4. 當(dāng)從一個(gè)線(xiàn)程中退出時(shí)調(diào)用NDC.remove方法,以便釋放資源。
下面是一個(gè)模擬記錄來(lái)自不同客戶(hù)端請(qǐng)求事件的例子,代碼如下:
1. 在進(jìn)入一個(gè)環(huán)境時(shí)調(diào)用NDC.push(String),然后創(chuàng)建一個(gè)NDC;
2. 所做的日志操作輸出中包括了NDC的信息;
3. 離開(kāi)該環(huán)境時(shí)調(diào)用NDC.pop方法;
4. 當(dāng)從一個(gè)線(xiàn)程中退出時(shí)調(diào)用NDC.remove方法,以便釋放資源。
下面是一個(gè)模擬記錄來(lái)自不同客戶(hù)端請(qǐng)求事件的例子,代碼如下:
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
public class TestNDC {
static Logger log = Logger.getLogger(TestNDC.class.getName());
public static void main(String[] args) {
log.info("Make sure %x is in your layout pattern!");
// 從客戶(hù)端獲得IP地址的例子
String[] ips = {"192.168.0.10","192.168.0.27"};
for (int i = 0; i<ips.length ; i++) // 模擬一個(gè)運(yùn)行方法
{
// 將IP放進(jìn) NDC中
NDC.push(ips[i]);
log.info("A NEW client connected, who's ip should appear in this log message.");
NDC.pop();
}
NDC.remove();
log.info("Finished.");
}
}
注意配置文件中的布局格式中一定要加上%x。系統(tǒng)輸出如下:import org.apache.log4j.NDC;
public class TestNDC {
static Logger log = Logger.getLogger(TestNDC.class.getName());
public static void main(String[] args) {
log.info("Make sure %x is in your layout pattern!");
// 從客戶(hù)端獲得IP地址的例子
String[] ips = {"192.168.0.10","192.168.0.27"};
for (int i = 0; i<ips.length ; i++) // 模擬一個(gè)運(yùn)行方法
{
// 將IP放進(jìn) NDC中
NDC.push(ips[i]);
log.info("A NEW client connected, who's ip should appear in this log message.");
NDC.pop();
}
NDC.remove();
log.info("Finished.");
}
}
INFO - Make sure %x is in your layout pattern!
INFO 192.168.0.10 - A NEW client connected, who's ip should appear in this log message.
INFO 192.168.0.27 - A NEW client connected, who's ip should appear in this log message.
INFO - Finished.
INFO 192.168.0.10 - A NEW client connected, who's ip should appear in this log message.
INFO 192.168.0.27 - A NEW client connected, who's ip should appear in this log message.
INFO - Finished.