意外错误是可能发生的其他类型的错误。事情以不可预见的方式中断。 意外错误通常是由 Python 异常在代码中的某个点引发但未被捕获而产生的。
如果日志记录已正确配置,任何未捕获的异常或错误都将触发 ERROR 日志,其中将包括堆栈跟踪。这些错误可能不会立即显现出来,需要进一步调查。
在尝试为已登录的用户发布新想法时,我们得到一个奇怪的行为,并在日志中看到以下错误。 如下图右上角所示,我们通过ERROR过滤来过滤问题:
如您所见,堆栈跟踪显示在一行中。这可能取决于您如何捕获和显示日志。 Flask 将自动生成一个状态码为 500 的 HTTP 响应。如果调用者还没有准备好接收 500 响应,这可能会触发更多的错误。
然后,堆栈跟踪将让您知道发生了什么故障。在这种情况下,我们可以看到 api_namespace.py 文件中的 80 行有一个 raise Exception 命令。这使我们能够定位异常。
Since this is a synthetic error that's been generated specifically as an example, it is actually easy to find out the root cause. In the example code, we are explicitly raising an exception, which produces an error. This may not be the case in a real use case, where the exception could be generated in a different place than the actual error. Exceptions can be also originated in a different microservice within the same cluster.
检测到错误后,目标应该是在微服务中通过单元测试来复制它,以生成异常。这将使我们能够在受控环境中复制条件。
如果我们对 Chapter10 中可用的 Thoughts Backend 代码进行测试,我们会因此而看到错误。请注意,日志显示在失败的测试中:
一旦在单元测试中重现了错误,修复它通常是微不足道的。添加单元测试以捕获触发错误的一组条件,然后修复它。新的单元测试将检测错误是否已在每个自动构建中重新引入。
要修复示例代码,请删除
raise 行代码。然后,事情将再次起作用。
有时,问题无法解决,因为它可能是外部的。也许我们数据库中的某些行有问题,或者另一个服务返回了格式不正确的数据。在这些情况下,我们无法完全避免错误的根本原因。但是,可以捕获问题,进行一些补救,然后从意外错误转变为预期错误。
请注意,并非每个检测到的意外错误都值得花时间处理。有时,未捕获的错误提供了关于问题所在的足够信息,这超出了 Web 服务应处理的范围;例如,可能存在网络问题,Web 服务无法连接到数据库。当您想花时间进行开发时,请使用您的判断力。