我们最近使用自定义过滤器向我们的 log4j 配置添加了一个过滤器。目标是停止一次又一次地重复相同的日志,但将其替换为:
日志 +“最后一行重复 x 次”
我们编写了以下过滤器,效果很好。但是后来,我们开始评论奇怪的死锁并挂断了tomcat5.5。
当我们删除此过滤器时,错误停止发生。(是的,我们对此非常确定)。
除了这个经验观察之外,JVM 的堆堆栈有许多 log4j 线程被阻塞并等待 tomcat 监视器被释放。
这是我们过滤器的代码。很基本。它出什么问题了 ?
public class RepeatFilter extends Filter {
String lastMessage;
Category lastLogger;
int repeatCount = 0;
@Override
public int decide(LoggingEvent event) {
// get the rendered (String) form of the message
String msg = event.getRenderedMessage();
if(msg == null || msg.startWith("Last message repeated "){
return Filter.NEUTRAL;
}
if(msg.equals(lastMessage)) {
repeatCount++;
return Filter.DENY;
} else {
if(repeatCount>0){
String msgToLog = "Last message repeated " + repeatCount + " time(s).";
repeatCount = 0;
lastLogger.log(event.getLevel(), msgToLog);
}
}
lastLogger = event.getLogger();
lastMessage = msg;
return Filter.NEUTRAL;
}
}
编辑:是的,当我们在过滤器中使用记录器时,它们是一个递归。事实上,服务器在 lastLogger.log(... ) 行之后挂起。但我们确实需要编写自定义消息(重复 x 次)。我们尝试在过滤器中不使用记录器,但我们还没有找到方法。
编辑 2:我使用 log4j 的 1.2.15 版本。
编辑3:我们将尝试的东西:
- 使我们所有的 appender 嵌套在 AsyncAppender 中
编辑 4:将每个附加程序包装在 asyncAppender 中并不能解决问题