65.9K
CodeProject 正在变化。 阅读更多。
Home

通过自动化错误处理,掌控你的错误!

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (3投票s)

2018年5月5日

CPOL

11分钟阅读

viewsIcon

19071

Coderr 自动检测和分析错误,让你可以专注于解决它们。

我做程序员已经二十多年了,从汇编到 Ruby 都接触过。在这期间,我一直对错误处理感到沮丧。在这篇文章中,我将解释原因以及我们为解决这个痛苦的问题所做的工作。

错误的问题

让我们从头开始,解释为什么用户报告的错误和日志文件并不完全匹配。

完美的错误报告的故事

如果你曾经在别人的应用程序中遇到过错误,你会怎么做?也许你会花时间写一份完整的错误报告,找到报告并提交的地方。你甚至可能在等待支持队列,以便能够报告这个错误。

毕竟,这就是我们期望每个用户都会做的事情。至于收到的报告,它们是否包含了足够的信息来理解错误发生的原因?

Screenshot from a very informative bug report

完美的错误报告就像独角兽。听起来很棒,但实际上并不存在——这没关系。在现实世界中,我们必须对用户报告的内容保持现实。说实话,大多数用户技术水平不够,无法认识到详细错误描述的重要性,或者不知道如何重现错误。

根据组织的类型和规模,错误报告可能会以几种不同的方式收到。也许你的情况或业务是客户直接打电话或发邮件给你。也许有一个专门的职能部门,如客服或支持部门,负责接收和登记错误报告。

问题在于需要管理。有人需要识别重复项,从不同的报告中提取信息,确定优先级,找到正确的日志文件,向用户发送状态更新等等。

日志的尾声

如果我们收到的错误报告无法帮助我们确定错误的根本原因,我们就需要做些其他事情。一种建议是尝试解释用户做了什么。另一种方法是反复试验,直到我们认为我们已经重现了用户的错误。

日志文件登场!

你们中的大多数可能都使用过日志文件,并且对基本的日志记录原则很熟悉。我的经验是,一个团队在应用程序生命周期的开始时能够很好地编写有用的日志行,但这种纪律随着时间的推移很难保持,即使是几个月后。

我们都知道这样的日志行

_logger.Error("Failed to save user", exception);

…没有帮助,因为它只是重复了错误消息,而没有提供异常被抛出原因的线索。

我们都经历过,尽管我们不希望如此。

"It works on my machine"

当用户发生错误时,我们不知道用户做了什么,我们还能说什么呢?错误报告没有帮助。日志包含了详细信息,但不是我们想要的。

经典的错误处理

我的经验是,用户如果还能继续工作,往往会忽略错误。由于他们有工作要做,写一份好的错误报告不是优先事项。发送报告也不是。

然而,如果用户无法绕过这个问题,他们可能会通过最便捷的方式报告。也许他们选择打电话或发邮件报告,而不是使用错误报告软件。由于很少有用户报告错误,因此对报告做出反应至关重要,因为很有可能其他许多用户已经遇到了相同的错误。

即使只有一个日志文件,你的所有环境中都存在错误。因此,有必要在开发、测试和生产环境中搜索异常。然后就是比较这些已记录的异常,看看它们是新的还是重复的。最后,你祈祷并希望日志中有足够的信息来理解异常发生的原因。

Coderr 解决方案

Coderr 的目的是让你重新掌控并全面了解正在发生的事情。Coderr 自动化了前面提到的许多任务。此外,Coderr 检测异常,收集关于它们发生原因的信息,分析信息,并最终引导你完成整个错误处理过程。

Error handling process

错误处理过程可以定义为一系列步骤,如上所述。让我进一步解释 Coderr 如何在整个过程中为你提供帮助。

发现

定期扫描日志文件中的错误,并依赖用户报告,会在错误发生和意识之间产生时间间隔。更不用说找到所有错误的能力了。

有了 Coderr,你就不需要这样做了。只需在应用程序中安装一个 nuget 包,并添加这三行代码。

var url = new Uri("https://report.coderr.io/");
Err.Configuration.Credentials(url, "yourAppKey", "yourSharedSecret");

// This line varies between the nuget libraries
Err.Configuration.CatchMvcExceptions();

就是这样!Coderr 生成的所有信息都来自这三行代码。

通过配置 nuget 库,Coderr 可以检测到所有未处理的异常,收集上下文信息,并将所有信息上传到 Coderr 服务器进行分析。收集到的上下文信息因 nuget 库而异。对于 Web 应用程序,可以是 POST 的视图模型或 HTTP 请求;对于 WPF 应用程序,可能是发生错误的窗口的屏幕截图。由于有了上下文信息,就不需要记录用户的操作来理解异常发生的原因了。在大多数情况下,Coderr 收集的信息足以重现错误。有关上下文收集的更多信息可以在本文的后面找到。

你还可以配置 Coderr,在检测到新的独特错误时立即通知你。如果需要,这可以实现即时关注和行动,因为 Coderr 始终在工作。

在 Coderr 中,“发现”部分提供了应用程序所有错误的完整视图,一目了然。在这里,目的是跟踪错误随时间的数量,同时提供控制和采取适当行动的机会。在这个视图中,你可以确定下一个要纠正的错误。

识别与优先级排序

Screenshot from the discover section in Coderr

在上方的屏幕截图中,“错误报告数量”与使用日志文件处理错误的人员将错误视为不同异常的次数相对应。或者更不可能的是,用户可以发送的错误报告数量。然而,Coderr 在此示例中将 560 个错误报告确定为仅代表 19 个独特错误。Coderr 将独特错误定义为“事件”。ITIL 将“事件”定义为

引用

IT 服务意外中断或 IT 服务质量下降。

在 Coderr (Community Server) 中,可以使用搜索功能来查找需要优先处理的错误。

你可以通过使用标签、上下文数据(例如请求 URL)或 Coderr 与错误一起打包的任何其他信息来限制搜索。

找到事件后,可以点击它进行查看。

Screenshot from the Discover incident view

Coderr 开箱即用地包含所有错误的应用程序版本,这使你能够查看相同的事件是否出现在你应用程序的最新版本或更多版本中。要纠正一个事件,你需要将其分配给自己或其他人。

重现错误

重现是错误纠正的基础,但你需要确信你正在纠正代码库的正确部分。否则,就有可能进行变通而不是修复 bug。

在 Coderr 的“发现”视图中将事件分配给自己后,就可以开始进一步分析它了。第二个顶部菜单项“分析”就是为此目的而设的。在“分析”中,Coderr 加载你分配的一个事件。下面显示了一个视图可能外观的示例。

The incident view when you want to understand why it happened.

  • 标签,在此示例中为 `console-application`,可用于对事件进行分类,以便更容易找到它们。有关如何使用标签的更多信息,请阅读我们的标签文档
  • 错误消息、异常类型和堆栈跟踪与日志文件相同。
  • 应用程序版本在检查特定代码库时很有趣。对于桌面应用程序尤其有用,因为客户可能运行的是不同版本。

屏幕截图中最重要的部分是上下文数据(在“上下文收集”区域)。在这里,Coderr 将关键信息与异常一起打包,在生成错误报告时。

上图显示了 Coderr 中选定视图模型的信息。nuget 包提供不同类型的上下文信息,这些信息都有助于重现错误。我们相信这是错误纠正的关键部分,使其更容易和更准确。

以下是 Coderr 的两个 nuget 包中的上下文信息示例。

WPF

对于 WPF,你可以获取失败窗口的屏幕截图和相应的视图模型。

Screenshot of the window that was active when the exception was thrown

The view model for the active window

ADO.NET

对于 ADO.NET,你可以获得失败的 SQL 语句,包括所有参数。你还可以获得 SQL 语句失败的连接的完整命令历史记录。

Command that was executed before the failing SQL

Information about the failing SQL command

自定义 Coderr

让我们看看 Coderr 如何根据你的要求进行自定义。

简化用户错误报告

我之前说过,由于大多数用户都有自己的习惯和个人偏好,很难让他们以类似的方式报告 bug。Coderr 通过在检测到错误时自动向用户显示错误对话框来解决这种不一致问题。

Screenshot showing the view that is displayed when an error is detected

上面的错误页面通过使用以下配置行在 ASP.NET MVC 中激活:

Err.Configuration.DisplayErrorPages();

错误视图可以自定义/替换,以便用户知道这是来自你的团队。你还可以让他们输入电子邮件地址,以便在事件纠正后通知他们。

Screenshot showing all received bug reports

当事件关闭时,Coderr 始终检查是否有用户正在等待通知。如果有,Coderr 会询问你是否要通知他们。

Asks if the dev want to send a message to all  users that wait on a status update.

我们建议点击“通知用户”,因为用户已经注册了状态更新,因此期望在事件解决时收到通知。选择“通知用户”后,会加载一个新的视图,允许你向用户撰写消息。

Dialog used to write the user notification

写一条消息并点击发送。Coderr 会向所有注册了此错误状态更新的用户发送电子邮件。

对于管理员来说,最大的好处是所有 bug 报告现在都会自动分配到 Coderr 中的正确事件。将所有 bug 报告集中在一个地方,可以大大简化管理,并向用户提供更新。

手动报告异常

Coderr 默认会捕获所有未处理的异常,但有时 try/catch 块是必需的。

为了能够手动报告异常,请使用 Err.Report 方法。第二个参数用于包含上下文数据,如下例所示。

try
{
    addUserInOrganization(id, user);
}
catch (Exception ex)
{
    Err.Report(ex, new{id, user});
}

报告后,信息将显示在 Coderr 服务器中,如下所示。

Result from  the code above

报告指南对此进行了详细说明。

已在使用 log4net?在过渡期使用我们的 log4net 适配器。它将自动向 Coderr 报告所有记录的异常。你的日志消息也会包含在内。

从异常中获取更多详细信息

在记录异常时,大多数日志记录库使用 exception.ToString(),它只包含异常信息的子集。Coderr 处理异常并从所有异常属性生成上下文集合。

一个经典的例子是 Entity Framework。有一个名为 DbEntityValidationException 的异常。记录时输出的内容类似:

引用

一个或多个实体验证失败。有关更多详细信息,请参阅“EntityValidationErrors”属性。

没什么帮助。你知道错误是什么,但不知道它是由什么引起的。在 stackoverflow 上有一个问题,有 651 票,询问如何获取实际的错误消息。

Coderr 开箱即用地为你提供帮助。以下是 Coderr 为该异常自动生成的上下文集合的一部分。

Screenshot from the entity framework validation exception

可以清楚地看到输入的属性值以及哪些属性验证失败。

因此,无需阅读每个异常的文档即可查看 exception.ToString() 包含哪些信息。

结论和你的错误处理下一步

我们都知道错误,因为它们是程序员生活的一部分。对我们中的一些人来说,这是一项日常工作。如果你对代码有很好的了解,那么你可以使用日志文件或日志文件处理程序来应对,这是目前管理错误的常用方法。

在本文中,我展示了 Coderr 如何自动化许多劳动密集型的错误处理任务,并获得更准确、更快速、最终更好的错误解决方案。了解 Coderr 能为你做什么的最好方法是自己尝试 Coderr。

本文重点介绍了我们的开源版本。你可以在我们的主页上比较版本,或从 github 下载 Community Server。

 
 
 
 
© . All rights reserved.