有两个方向可以解决这个问题:系统端和开发端。从系统方面(即在应用程序部署和运行之后)处理这个问题已经有几个答案。但是,我想谈谈开发方面。
我看到的一个非常常见的模式是在每个级别记录异常。我看到 UI 组件、EJB、连接器、线程、帮助类、pojo 等,等等,记录所有发生的异常。在许多情况下,无需费心检查日志级别。这具有您遇到的确切结果以及使调试和故障排除花费比必要更多的时间,因为必须筛选所有重复的错误。
我的建议是在代码中执行以下操作:
思考。 并非每个异常都是致命的,而且在许多情况下实际上是无关紧要的(例如IOException
,来自close()
流上的操作。)我不想说“不要记录异常”,因为您当然不想错过任何问题,所以在最坏的情况下,将日志语句放在调试级别的条件检查中
if(logger.isDebugEnabled()){
// log exception
}
仅在顶层记录。 我确信这会遇到一些负面影响,但我的感觉是,除非类是应用程序或组件的顶级接口,或者异常不再被传递,否则不应记录异常。换句话说,如果异常被重新抛出、包装并抛出或声明为从方法中抛出,则不要在该级别记录它。
例如,第一种情况是导致日志语句过多的问题,因为它可能是调用者和被调用的任何东西也会记录异常或有关错误的某些语句。
public void something() throws IllegalStateException{
try{
// stuff that throws some exception
}catch(SomeException e){
logger.error(e); // <- NO because we're throwing one
throw new IllegalStateException("Can't do stuff.",e);
}
}
既然我们正在扔它,请不要记录它。
public void something() throws IllegalStateException{
try{
// stuff that throws some exception
}catch(SomeException e){
// Whoever called Something should make the decision to log
throw new IllegalStateException("Can't do stuff.",e);
}
}
但是,如果something
停止异常的传播,它应该记录它。
public void something(){
try{
// stuff that throws some exception
}catch(SomeException e){
if(logger.isLogLevelEnabled(Log.INFO)){
logger.error(e); // DEFINITELY LOG!
}
}
}