在全部捕获或基本异常类中记录异常是否更明智?


15

我正在重构一个相当大的Web应用程序。主要问题之一是不一致的错误处理,我正在尝试提出一个明智的策略。我已经通过set_error_handler创建了一个自定义错误处理程序,该处理程序从本质上转变了ErrorExceptions中的 PHP错误以及一个直接从Exception继承的自定义基本异常类。

在生产环境中,我正在通过set_exception_handler使用通用异常捕获功能,并且将要添加异常记录*的功能。我的难题是在基本异常类或全部捕获中执行实际日志记录的位置。

我想到了将其记录在全部功能中的几个原因:

  • 代码中有很多异常需要转换为基本异常类的适当子代。在此之前,并非所有异常都会被记录。
  • 总括而言,以某种方式感到更自然,基本异常类不应该仅仅这样做。(这可能是一个单一的责任原则,但可能只是一种误导)

以及登录基本异常类的原因之一:

  • 目前,全部收集仅用于生产。将其引入我们的其他环境(开发,测试)很容易,但是这需要进行一些调整,因为错误在每个环境中的处理方式不同,在生产中将其转换为404/503错误页面。

在哪里记录异常有可接受的做法吗?

*日志记录将首先涉及写入文本文件,并且可能会演变成发送某些类型异常的邮件。


@unholysampler的回答提示了一些说明:

我面对的是2 * 10 ^ 6 sloc代码库,其中包含许多我无法控制的第三方内容,而我确实有一些代码可以控制PHP中的preddates异常。而且还有一些糟糕的最新代码,我们正从长期的沉重压力中恢复过来,在这些压力下,我们实际上不得不停止思考并被黑了。

我们正在积极进行重构以解决所有不一致问题,并引入明智的错误处理方法,但这将需要一些时间。在达到正确处理错误的程度之前,我对该怎么办更感兴趣。在某个时候,我可能会问另一个关于明智的例外策略的问题。

记录背后的主要动机是,每当生产中发生任何问题时,都会在我的手机上收到一封电子邮件。我不在乎数据转储是否会很大,如果确实如此,我将有一份cron作业,不时地删除旧的。

Answers:


11

简而言之,只有在处理异常时才应记录该异常的存在。

当您引发异常时,这是因为您的代码已达到无法正确执行的状态。通过引发异常,您可以向程序表示一条有关发生的错误的特定消息。在您可以适当处理异常之前,您不应捕获异常。

您在主应用程序中编写的代码应注意可以引发的异常类型以及何时引发这些异常。如果您不能做任何有例外的工作,请不要抓住它。在处理异常之前,请勿记录异常。只有处理代码才能知道异常在程序流的上下文中的含义以及如何对其进行响应。在此处写日志消息可能很有意义。如果使用日志记录框架,则可以为消息设置日志级别并可能对其进行过滤。这对于可能发生的异常有效,但不是很关键,可以从干净的状态中恢复。

您的例外情况是万能的,这是您为避免代码崩溃而做出的最后一次努力。如果到此为止,您将记录所有状态和错误信息。然后,您将尽力告诉用户在程序停止运行之前该程序已崩溃。您的目标应该是永远不要执行此代码。

将日志嵌入到基类中并不遵循上述准则。基类对代码状态一无所知。(具有堆栈跟踪不算在内,因为您不会编写基于解析进行决策的代码。)基类无法执行任何操作来指示严重性或异常的处理方式。您不希望每次都有一个简单的异常就可以进行干净的处理并从中恢复时,就不需要大量的数据转储和堆栈跟踪。


我对您的答案提示的问题做了一些说明。根据我的收集,在您建议登录全部问题的实际问题上?
yannis 2011年

1
@YannisRizos:是的,您应该将“包罗万象”作为第一步。我所说的“包罗万象”更多是为了确保您没有将其用作代码流的正常部分。实施未处理的异常处理程序非常重要,因为它使您每次代码执行每项不好的操作时都可以获得大量信息。
unholysampler 2011年

是否有日志记录框架可以方便地处理“这里有很多东西,除非被取代,否则应该对其进行记录”的概念?看到异常的每一层都可以取代前一层的数据,除非在堆栈展开过程中抛出新异常时,最后一个日志报告不会被取代,因此将被记录。没有框架支持这种模式吗?
2015年

3

如果您的语言/运行时不容易让您确定异常的来源,则可以在抛出异常时进行记录。C ++和某些JS引擎在捕获到异常时不会公开该异常的文件行或调用堆栈,但是在构造异常时此信息可用。

我们的解决方案是提供一种机制,该机制使用运行时配置来在尝试诊断这些问题时启用日志记录异常类型以及廉价堆栈。


+1这绝对是一个很好的案例记录在抛出... PHP确实在追赶提供完整的堆栈跟踪了,所以我可能会走另一条路...
雅尼斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.