在Java中记录更好的异常信息
我正在使用Spring、Hibernate和其他一些库(包括用于日志记录的ApacheLog4j)开发一个更大的JavaWeb应用程序。我正在进行的一个项目是重写代码遗留区域(我没有编写!)中的大量异常,以提供更合理的信息。典型的异常块如下所示:在Java中记录更好的异常信息,java,design-patterns,exception,exception-handling,Java,Design Patterns,Exception,Exception Handling,我正在使用Spring、Hibernate和其他一些库(包括用于日志记录的ApacheLog4j)开发一个更大的JavaWeb应用程序。我正在进行的一个项目是重写代码遗留区域(我没有编写!)中的大量异常,以提供更合理的信息。典型的异常块如下所示: try { //Some Hibernate business here } catch (Exception e) { //Yes, Exception. That's not just me being general. I find th
try {
//Some Hibernate business here
}
catch (Exception e) { //Yes, Exception. That's not just me being general. I find this especially frustrating.
log4j.error("Fail to XXXXXX"); //again, real
throw new MyException();
}
try {
//Some Hibernate business here
}
catch (Exception e) { //Yes, Exception. That's not just me being general
log4j.error("Fail to XXXXXX", e); //again, real
throw new MyException(e);
}
正如您所猜测的,这会导致一些具有挑战性的日志。我正在寻找一种标准的方法来从这些异常中获得更好的信息。如果有帮助的话,它们中的大多数都会包装Hibernate调用。这是一个与我刚才写的类似的典型块:
try {
myList.add( ((myClass) commonService.getRecordByTableId(myClass.class, ID)).toString() );
} catch (ServiceException e) {
log4j.error("Failed to retrieve record from table myClass for id " + ID);
e.printStackTrace();
}
在这里,我从数据库中提取一条记录并将其添加到列表中。在catch块中,我记录我认为是关于
try
块正在做什么的合理消息,并打印堆栈跟踪。所以,我的问题是:一般来说,为了获得更好的错误诊断信息,我还可以/应该做些什么吗?是的,在第一块中,应该是这样的:
try {
//Some Hibernate business here
}
catch (Exception e) { //Yes, Exception. That's not just me being general. I find this especially frustrating.
log4j.error("Fail to XXXXXX"); //again, real
throw new MyException();
}
try {
//Some Hibernate business here
}
catch (Exception e) { //Yes, Exception. That's not just me being general
log4j.error("Fail to XXXXXX", e); //again, real
throw new MyException(e);
}
Java允许您链接异常,因此您应该这样做。此外,当使用Log4J时,您还可以发送异常,这样它也会在日志中打印异常堆栈跟踪。printStackTrace()
不会将跟踪添加到日志中。将异常提供给log4j会将其打印到您的日志文件中,其中上下文有意义:
log4j.error("Failed to retrieve record from table myClass for id " + ID, e);
在异常处理中,日志记录和重新抛出是一种流行的反模式。你不应该那样做。您需要决定是捕获异常,然后正确处理它(包括日志记录),还是不捕获它并允许它传递到更高的级别(或者如果它是选中的异常,则在运行时异常中重新刷新/包装它) 如果您这样做(log+rethrow),那么上游代码就无法知道您已经记录了异常,因此同一异常可能会被记录两次或更多次,这取决于异常必须经过的层数,以及任意决定记录并重新抛出它的层数。这将使阅读日志和理解日志成为一场彻头彻尾的噩梦 此外,您可能会争辩说,抛出和捕获异常是代价高昂的操作,所有这些捕获和重新抛出都无助于提高运行时的性能 因此,如果您选择实际处理异常,那么接受它不是正确的方法(即使您记录了一些消息)。至少,您需要记录跟踪:
log4j.error("Failed to retrieve record from table myClass for id " + ID, e);
除了其他人提到的以外,还有几件事:
+1.如果可以的话,我也会加分。我已经厌倦了看到一个堆栈跟踪有几个“回声”之前。是的,正如我。令人惊讶的是,有多少“认真”的开发人员认为日志记录和重放是一个足够好的处理大多数异常。+ 1,良好的调用。在这个项目中发生的很多事情让我非常难过,我正在努力使它成形达尔索,我喜欢反模式这个词。