2011-11-03 186 views

回答

10

這可以在Log4J的後繼者Logback中完成。

Logback旨在作爲流行的log4j項目的繼任者,從log4j離開的地方開始。

參見Sifting Appender

文檔的SiftingAppender處於其引用和配置嵌套追加程序容量是唯一的。在上面的例子中,在SiftingAppender中將存在嵌套的FileAppender實例,每個實例通過與「userid」MDC密鑰關聯的值標識。每當爲「userid」MDC鍵分配一個新值時,將從頭開始構建一個新的FileAppender實例。 SiftingAppender會跟蹤它創建的appender。未使用30分鐘的追加者將被自動關閉並丟棄。

在該示例中,它們基於MDC值爲每個用戶生成單獨的日誌文件。 可以根據您的需要使用其他MDC值。

+0

但是使用Logback將意味着所有的日誌語句都必須正確更改? –

+1

請參閱橋接舊版API http://slf4j.org/legacy.html – Ceki

9

這對log4j也是可能的。你可以通過實現你自己的appender來做到這一點。我想最簡單的方法是 子類AppenderSkeleton

所有的日誌記錄事件都以您必須實現的append(LoggingEvent event)方法結束。

在這種方法中,你可以通過event.getMDC("nameOfTheKeyToLookFor");

訪問MDC那麼你可以使用這些信息來打開寫入文件。 看看RollingFileAppender這些標準appender的執行情況,可能會有所幫助。

我自己在一個應用程序中使用這種方法將不同線程的日誌分成不同的日誌文件,它工作得很好。

+0

我沒有使用RollingFileAppender。 FileAppender有可能嗎? –

+0

我只提到了RollingfileAppender作爲如何實現appender的例子。基本上你可以在append方法中做任何你想做的事情。 – Wolfgang

5

我苦苦掙扎了一段時間纔在log4j中找到類似SiftingAppender的功能(由於某些依賴關係,我們無法切換到logback),最後出現了一個程序化的解決方案,運行得非常好,使用MDC和追加記錄器運行時間:

// this can be any thread-specific string 
String processID = request.getProcessID(); 

Logger logger = Logger.getRootLogger(); 

// append a new file logger if no logger exists for this tag 
if(logger.getAppender(processID) == null){ 

    try{ 
    String pattern = "%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n"; 
    String logfile = "log/"+processID+".log"; 

    FileAppender fileAppender = new FileAppender(
     new PatternLayout(pattern), logfile, true); 
    fileAppender.setName(processID); 

    // add a filter so we can ignore any logs from other threads 
    fileAppender.addFilter(new ProcessIDFilter(processID)); 

    logger.addAppender(fileAppender); 
    }catch(Exception e){ 
    throw new RuntimeException(e); 
    } 
} 

// tag all child threads with this process-id so we can separate out log output 
MDC.put("process-id", processID); 

//whatever you want to do in the thread 
LOG.info("This message will only end up in "+processID+".log!"); 

MDC.remove("process-id"); 

以上只是附加的過濾器檢查特定的進程ID:

public class RunIdFilter extends Filter { 

    private final String runId; 

    public RunIdFilter(String runId) { 
    this.runId = runId; 
    } 

    @Override 
    public int decide(LoggingEvent event) { 
    Object mdc = event.getMDC("run-id"); 

    if (runId.equals(mdc)) { 
     return Filter.ACCEPT; 
    } 

    return Filter.DENY; 
    } 
} 

希望這有助於一點。

+0

如何在Log4j 2中寫入相同的過濾器? –

+0

在第一個塊中添加代碼的位置? – NaiveCoder

+0

@NaiveCoder您想要啓動MDC篩選的任何位置。 – bpodgursky