在Java中记录更好的异常信息

and*_*kus 4 java design-patterns exception-handling exception

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

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();
}
Run Code Online (Sandbox Code Playgroud)

你可以猜到,这会产生一些具有挑战性的日志.我正在寻找一种标准方法来从这些例外中获得更好的信息.如果有帮助的话,大多数都会包装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();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我从数据库中提取记录并将其添加到列表中.在catch块中,我记录了我认为关于try块正在做什么的合理消息,并打印堆栈跟踪.所以,我的问题是:为了获得诊断错误的更好信息,我还能做什么/应该做些什么呢?

Gui*_*ume 10

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

如果你这样做(log + rethrow),那么上游代码就无法知道你已经记录了异常,因此同样的异常可能被记录两次或更多次,这取决于异常需要多少层通过,以及任意决定记录并重新抛出它的层.这将使阅读日志并使它们成为一个完整的噩梦.

此外,您可能会认为抛出和捕获异常是昂贵的操作,所有这些捕获和重新抛出都无助于您在运行时的性能.

因此,如果您选择实际处理异常,那么吞咽它就不是正确的方法(即使您记录了一些消息).至少,您需要记录跟踪:

log4j.error("Failed to retrieve record from table myClass for id " + ID, e);
Run Code Online (Sandbox Code Playgroud)

  • +1.如果可以的话,也会给予更多积分.我已经厌倦了在它之前看到有几个"回声"的堆栈跟踪. (2认同)

rsp*_*rsp 5

printStackTrace()不会将跟踪添加到您的日志中。向log4j提供异常会将其打印到上下文有意义的日志文件中:

log4j.error("Failed to retrieve record from table myClass for id " + ID, e);
Run Code Online (Sandbox Code Playgroud)