2011-11-03 187 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