抛出异常与记录

时间:2014-02-27 15:03:44

标签: java exception logging try-catch

以下是编写良好实践的方法吗?

try {
    //my code here
} catch (Exception e) {
    logger.error("Some error ", e);
    throw new MyCustomException("Some error ", e);
}

此外,我应该.. ..

  • 只使用记录器?
  • 只抛出异常?
  • 两者兼而有之?

我理解使用throw我可以在callstack的另一部分中捕获异常,但是可能额外的日志记录有一些隐藏的好处,并且也很有用。

6 个答案:

答案 0 :(得分:13)

通常情况下,我认为您应该记录重新抛出。同时执行这两个操作只会导致每个图层一次又一次地记录异常,这使得日志难以阅读。更糟糕的是,很难弄清楚你实际拥有多少错误 - 是7个错误,还是记录了相同错误的7层应用程序?

这意味着如果您取消异常,则会记录它并说明为什么您认为不值得重新抛出。

另一方面,如果你重新抛出异常,你知道它会被捕获并被抑制(在这种情况下捕获器会记录异常以及它被抑制的原因),或者它将从您的应用程序中冒出来并被应用程序容器捕获,该容器将捕获并记录异常。每个异常在日志中只显示一次。

答案 1 :(得分:6)

我在某些情况下使用两者,记录并抛出异常。特别是,它在API中很有用。通过抛出异常,我们允许调用者处理它,通过记录,我们可以自己确定它的根本原因。

并且,如果调用者在同一系统中,那么如果我们在每个catch中添加日志,则会有重复的日志。

答案 2 :(得分:3)

使用您建议的模式时,通常会在日志中多次报告错误事件。此外,在阅读日志时,它们之间的连接并不总是很简单。

我个人更喜欢只记录错误事件一次,并且在较高的调用级别中执行此操作。因此,我几乎从不记录和再次抛出。我通常让异常进入调用堆栈,直到它到达可以某种方式处理的上下文,这就是我记录的地方。

如果异常被包装并重新正确抛出,则应该从单个日志消息的堆栈跟踪中清楚地看到上下文。

答案 3 :(得分:2)

正确的答案是:“这取决于”

您通常希望记录您捕获的异常,因为它们对应于出错的地方。这就是为什么代码分析工具(如声纳)会在您不记录它们时发出警告的原因。

考虑以下目标:解析文件。在解析文件时,您实际上尝试解析每一行。有时某些行会出错,因此您不希望因此而停止解析文件。在这种情况下,您可能只想记录错误的行并继续保存文件。 但是,想象一下,在某些时候,您在阅读时会遇到I / O异常(例如,某些其他程序在您访问该文件时删除了该文件)。

在这种情况下,您可能希望在日志中记录遇到的错误,并抛出一个新的异常以停止处理整个文件。

简而言之,你必须考虑做什么是最好的事情。但这两种做法都不错。

答案 4 :(得分:1)

我认为您可能需要明智地使用该模式。正如您在上面所写的那样,对于每个例外,您将记录2个堆栈跟踪,这可能会在您的日志中填充过多的信息。

关于伐木与投掷,它们是两个不同的问题。抛出异常会中断执行,阻止任何进一步的工作,也许回滚数据库提交等。日志记录只会将信息转储到日志文件(或其他地方)。它更适用于调试,而且通常更难以测试。

答案 5 :(得分:0)

我知道这是个老问题,但我有另一个解决方案。

考虑一下。您可以将问题记录在 catch 块中并抛出一个新的 unchecked 异常(当然是将前一个异常传入内部)。在这样的解决方案中,日志没有溢出,异常仍然冒泡到最高级别。

try {
    //my code here
} catch (SomeException e) {
    logger.error("Some error occured", e);
    throw new MyUncheckedException("Some error ", e);
}