2011-10-28 30 views
3

我正在使用Spring,Hibernate和其他一些库(包括Apache log4j进行日志记录)处理大型Java Web应用程序。我的一个正在进行的项目是重写遗留区域中的大量例外(我没有写!)以提供更多明智的信息。一个典型的异常块如下所示:在Java中记录更好的异常信息

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(); 
} 

正如你所猜测的,这使得一些具有挑战性的日志成为可能。我正在寻找一种标准的方式来从这些例外中获得更好的信息。如果有帮助的话,他们大多会包装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块正在做什么的明智信息,并打印堆栈跟踪。所以,我的问题是:为了获得更好的诊断错误信息,我还有其他事情可以/应该做些什么?

回答

10

在异常处理,记录并重新投掷是一种流行的反模式。你不应该那样做。您需要在捕获异常,然后正确处理它(包括日志记录)或不捕获它并允许它传递到更高级别(或重新抛出它/将它包含在运行时异常(如果它是检查异常))之间做出决定。

如果你这样做(日志+重新抛出),那么有没有办法为上游代码知道你已经登录异常,所以相同的异常可能会被记录两次或更多,这取决于有多少层例外必须经过,并且任意层决定登录并重新抛出它。这将使阅读日志,并认为它们是一个完整的噩梦。

你也可以争辩说,抛出和捕获异常是昂贵的操作,所有这些捕获和重新抛出不会帮助你在运行时的性能。

因此,如果您选择实际处理异常,那么吞咽它并不是正确的方法(即使您记录了某条消息)。最起码,你需要登录跟踪:

log4j.error("Failed to retrieve record from table myClass for id " + ID, e); 
+2

+1。如果可以的话,也会给予更多的观点。我非常厌倦了在它之前看到有几个“回声”的堆栈轨迹。 –

+1

是的,就像我一样。令人惊讶的是,有多少“严肃”的开发者认为日志记录和重新投掷对于大多数例外来说是足够好的处理。 – Guillaume

+0

+1,良好的通话。有很多关于这个项目发生的事情让我非常难过,我试图将它变成一个整体。 :D – andronikus

1

是的,在第一个模块,它应该是这样的:

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时,您也可以发送异常,以便它将在日志中打印异常堆栈跟踪。

4

printStackTrace()不会将跟踪添加到您的日志。直供例外的log4j将它放在上下文中有意义打印到日志文件:

log4j.error("Failed to retrieve record from table myClass for id " + ID, e); 
2

除了几件事情是什么其他人所说的:

  1. 利用不同的日志记录级别:信息;警告;等等
  2. 从#1开始,我会放弃这些printStackTrace()调用。如果您想在控制台中记录错误,请通过记录器进行操作。这样,即使对于控制台,您也可以获得过滤级别的好处。