出于日志目的捕获 RuntimeException 是一种不好的做法吗?
Is it bad practice to catch RuntimeException for logging purposes?
我发现捕获 RuntimeException 通常被认为是不好的做法,因为它们无法更正并且通常是程序员错误。
但是,我们有一个(疯狂的)大型应用程序,其中任何部分的更改都会产生无法预料的后果(是的,这本身就是一个问题)。
现在开始在应用程序的顶层捕获和记录 RuntimeExceptions 的想法已经出现,这样我们就可以更有效地解决出现的此类出血问题。
像每个优秀的 Java 团队一样,我们有一个可爱的热心 Bob 叔叔追随者,他绝对禁止我们这样做。
这样做到底有多糟糕?真的没有可以甚至推荐这样做的情况吗?
捕获 RuntimeExceptions 不是问题,它们是异常,因此可以捕获并正确处理。如果 Java 开发人员希望您不要捕获 RuntimeExceptions,他们会将其命名为 RuntimeError。
糟糕的是捕获 RuntimeExceptions,静静地丢弃它们并继续 运行 就好像什么都没有发生过一样。 RuntimeExceptions 用于通知 developer/user 程序明显离开预期状态的关键问题和情况。至少应该记录下来,并且您应该尝试让程序恢复到舒适状态。
这么大的失败后能不能继续,完全看你的应用了。 Web 服务器即通常捕获所有异常和错误,然后重新启动相应的 Servlet,以便它们可以继续为请求提供服务。
完全取决于流量和你在哪里捕获它。
如果您正在使用 Spring,请考虑编写一个 ControllerAdvice。在这里阅读更多 https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html
在需要时捕捉 RuntimeException
不是 不好的做法。
它在使用第 3 方代码时非常有用,它抛出自己的异常扩展 RuntimeException
然后您 需要 捕获它以便进行良好的异常处理。
也在 JSP 中 捕捉 RuntimeException
有时有助于防止页面因为 NullPointerException
.
而根本不显示
赶上 RuntimeException
并不总是坏事。但即使您的团队决定不捕获 RuntimeException
的,您也可以随时捕获它,记录一些东西然后重新抛出它。它根本不会改变您的应用程序逻辑。
除了日志消息之外,现在几乎所有的记录器库都有可能记录关于异常的不同细节(比如堆栈跟踪和所有嵌套异常)。
public void doStuff(String param){
try {
process(param);
} catch(RuntimeException e) {
logger.error("Something weird happened while processing " + param, e);
throw e;
}
}
以下是关于上下文的更新,谢谢Ralf Kleberhoff指出
最好只在应用程序的顶层记录有关 RuntimeException
(或任何其他 Exception
)的消息,以避免在日志中出现关于同一异常的重复消息。
如果您只想添加一些上下文(如参数值,如 Ralf Kleberhoff 所述)并且它不是应用程序顶层 catch
(您确定,顶层 catch
实际存在),最好创建一个新的 Exception
并将原来的 Exception
作为 cause
添加到新的
public void doStuff(String param){
try {
process(param);
} catch(RuntimeException e) {
throw new RuntimeException("Something weird happened while processing " + param, e);
}
}
private void process(String value){
throw new IllegalStateException("Not implemented yet!");
}
我发现捕获 RuntimeException 通常被认为是不好的做法,因为它们无法更正并且通常是程序员错误。
但是,我们有一个(疯狂的)大型应用程序,其中任何部分的更改都会产生无法预料的后果(是的,这本身就是一个问题)。
现在开始在应用程序的顶层捕获和记录 RuntimeExceptions 的想法已经出现,这样我们就可以更有效地解决出现的此类出血问题。
像每个优秀的 Java 团队一样,我们有一个可爱的热心 Bob 叔叔追随者,他绝对禁止我们这样做。
这样做到底有多糟糕?真的没有可以甚至推荐这样做的情况吗?
捕获 RuntimeExceptions 不是问题,它们是异常,因此可以捕获并正确处理。如果 Java 开发人员希望您不要捕获 RuntimeExceptions,他们会将其命名为 RuntimeError。
糟糕的是捕获 RuntimeExceptions,静静地丢弃它们并继续 运行 就好像什么都没有发生过一样。 RuntimeExceptions 用于通知 developer/user 程序明显离开预期状态的关键问题和情况。至少应该记录下来,并且您应该尝试让程序恢复到舒适状态。
这么大的失败后能不能继续,完全看你的应用了。 Web 服务器即通常捕获所有异常和错误,然后重新启动相应的 Servlet,以便它们可以继续为请求提供服务。
完全取决于流量和你在哪里捕获它。
如果您正在使用 Spring,请考虑编写一个 ControllerAdvice。在这里阅读更多 https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html
在需要时捕捉 RuntimeException
不是 不好的做法。
它在使用第 3 方代码时非常有用,它抛出自己的异常扩展 RuntimeException
然后您 需要 捕获它以便进行良好的异常处理。
也在 JSP 中 捕捉 RuntimeException
有时有助于防止页面因为 NullPointerException
.
赶上 RuntimeException
并不总是坏事。但即使您的团队决定不捕获 RuntimeException
的,您也可以随时捕获它,记录一些东西然后重新抛出它。它根本不会改变您的应用程序逻辑。
除了日志消息之外,现在几乎所有的记录器库都有可能记录关于异常的不同细节(比如堆栈跟踪和所有嵌套异常)。
public void doStuff(String param){
try {
process(param);
} catch(RuntimeException e) {
logger.error("Something weird happened while processing " + param, e);
throw e;
}
}
以下是关于上下文的更新,谢谢Ralf Kleberhoff指出
最好只在应用程序的顶层记录有关 RuntimeException
(或任何其他 Exception
)的消息,以避免在日志中出现关于同一异常的重复消息。
如果您只想添加一些上下文(如参数值,如 Ralf Kleberhoff 所述)并且它不是应用程序顶层 catch
(您确定,顶层 catch
实际存在),最好创建一个新的 Exception
并将原来的 Exception
作为 cause
添加到新的
public void doStuff(String param){
try {
process(param);
} catch(RuntimeException e) {
throw new RuntimeException("Something weird happened while processing " + param, e);
}
}
private void process(String value){
throw new IllegalStateException("Not implemented yet!");
}