“在我的机器上工作” - 如何修复不可重复的错误?

时间:2009-07-09 09:11:08

标签: debugging testing

偶尔,尽管经过了所有的测试工作,但我还是遇到了一个客户的错误报告,我无法在办公室里重现。

"Works on my machine" syndrome]
Apologies to Jeff用于“借用”徽章)

我有一些“工具”,我可以尝试找到并修复这些工具,但总觉得我有点像刀和它一样: -

  • 要求客户提供越来越多的上下文:(systeminfo)
  • 我们的应用程序中的日志文件
  • 与客户进行特别测试以尝试更改行为
  • 为客户提供具有额外诊断功能的新构建
  • 想一想洗澡中的问题......
  • 实地考察(假设客户温暖而阳光充足)

是否有设置程序或其他技术,而不是任何人用来解决这样的问题?

22 个答案:

答案 0 :(得分:27)

好的调试器的一个属性,我认为他们的工具包中总是有很多武器。他们似乎永远不会被“卡住”太长时间,他们总会尝试其他的东西。我知道要做的一些事情:

  1. 要求内存转储
  2. 在客户端计算机上安装远程调试程序
  3. 为构建添加跟踪代码
  4. 添加日志代码以进行调试
  5. 添加效果计数器
  6. 将配置参数添加到各种可疑代码中,以便我可以打开和关闭功能
  7. 重写并重构可疑代码
  8. 尝试在不同的操作系统或计算机上本地复制问题
  9. 使用应用程序验证程序等调试工具
  10. 使用第三方负载生成工具
  11. 内部编写模拟工具,以便在上述失败时生成负载
  12. 使用Glowcode等工具分析内存泄漏和性能问题
  13. 从头开始重新安装客户端计算机
  14. 获取注册表转储并在本地应用
  15. 使用注册表和文件观察工具
  16. 最终,我发现这个bug只是因为我的坚持而放弃了某种敬畏。或者客户端意识到它可能是机器或客户端安装或配置问题。

答案 1 :(得分:10)

广泛的记录通常有帮助。

答案 2 :(得分:9)

最简单的方法是始终看到客户在行动(假设客户很容易重现)。通常,由于客户的计算机环境问题,与其他程序的冲突等问题而出现问题 - 这些是您无法在开发平台上捕获的细节。所以现场访问可能很有用;但如果这不方便的话,像RealVNC这样的工具也可能有助于让你看到顾客“做他们的事”。

(观察客户的行动还可以让您在他们可能拥有的任何WTF时刻抓住他们)

现在,如果问题是间歇性的,那么事情会变得更加复杂。解决此问题的最佳方法是在可能发生问题的位置记录有用信息,并可能使用Splunk之类的工具在分析期间索引日志文件。在这种情况下,诊断构建(即具有额外的日志记录)可能很有用。

答案 3 :(得分:6)

我正处于实施自动错误报告系统的过程中,该系统会从应用程序遇到的任何异常中向我发送信息(目前通过电子邮件,尽管您可以使用网络服务)。

这样我就能得到(几乎)如果我坐在VS2008面前我会做的所有信息,这真的有助于我解决问题所在。

客户通常(sorta)留下深刻印象,一旦他们遇到问题我就会立即知道他们的问题!

此外,如果您使用Application.ThreadException错误处理程序,您也可以发回有关意外异常的信息!

答案 4 :(得分:3)

我们会逐步使用您提到的所有方法,从最简单的方式开始,然后继续努力。

但是你忘了有时硬件有问题。例如,内存可能出现故障,并且一些计算密集型代码会奇怪地抛出奇怪的诊断异常。对于cource,它适用于您的机器,因为您没有有故障的硬件。

需要有经验来识别此类错误,并坚持要求客户尝试在另一台计算机上安装该程序或进行硬件检查。有一点很有帮助的是良好的错误处理 - 当你的代码抛出一个异常时,它应该提供细节,而不只是指出一些东西是坏的。通过良好的错误指示,可以更轻松地识别与故障硬件相关的可疑问题。

答案 5 :(得分:2)

我们使用EurekaLog直接发布到FogBugz,取得了很好的成功。这给我们带来了一个错误报告,其中包含一个调用堆栈,以及相关的系统信息(运行的其他进程,内存,网络详细信息等)和屏幕截图。客户偶尔也会输入更多信息,这很有帮助。在大多数情况下,肯定会更容易,更快地修复错误。

答案 6 :(得分:2)

我认为最重要的事情之一就是能够就客户报告的内容提出合理的问题......通常他们没有提到他们认为不相关的事情,但实际上是关键。

心灵感应也很有用......

答案 7 :(得分:1)

我发现一种有用的技术是使用集成的“诊断”模式构建应用程序(启动应用程序时通过命令行开关启用)。这当然避免了使用额外的日志记录创建自定义构建的需要。

否则,听起来你所做的就像任何方法一样好。

答案 8 :(得分:1)

Copilot(假设客户在寒冷多雨的地方:)

答案 9 :(得分:1)

我认为跟踪用户采取的行动可能会导致我们失败或选择性失败的原因。但大多数时候,用户都无法准确描述与应用程序的交互,自动截屏(如果是桌面应用程序。对于.net应用程序,您可以检查Jeff的UnhandledExceptionHandler)。记录改变对象状态的所有重要操作也可以帮助我们理解它。

答案 10 :(得分:1)

通常的做法是期望这样的事情发生并添加大量的日志记录信息。当然,你不能从一开始就启用它,但只有在发生这种情况时才启用它。

通常客户不喜欢安装新版本或某些诊断工具。调试不是他们的工作。对于像这样的案件来说,访问客户很少是一种选择。您必须尽可能少地让客户参与进来。更改交换机并向您发送日志文件是可以的 - 除此之外的任何内容都太多了。

我喜欢在洗澡时思考问题的另一种选择。我将从尝试找出我的机器和客户端配置之间的差异开始。

答案 11 :(得分:1)

我也有这些问题。我的解决方案是添加大量日志记录,并为客户提供包含所有可能的调试信息的调试版本。然后确保Dr Watson(它在Windows NT上)创建了一个包含足够信息的内存转储。 在调试器中加载内存转储后,我可以找出崩溃的位置和原因。

编辑:哦,这显然只有在应用程序暴力终止时才有效......

答案 12 :(得分:1)

作为做网络的软件工程师(预订/商店/会员系统等),对我们来说最重要的是尽可能多地从客户那里获取信息。

来自

  

它破了!

  它打破了! &安培;这是截图   我挑选的每一个选项   生成此特定报告

减少了我们重现和修复问题所花费的时间。

这可能是显而易见的,但有时需要相当多的追逐来从我们的客户那里获得这种信息!但是,只有那些你发现他们并非实际做他们所说的那样的时刻,这是值得的。

答案 13 :(得分:0)

您可以使用Microsoft SharedViewTeamViewer等工具连接到远程PC并直接在现场检查问题。当然,您需要与客户合作。

答案 14 :(得分:0)

正如许多人所提到的,广泛的日志记录,并在出现问题时向客户端询问日志文件。此外,随着我​​对Web应用程序的更多工作,我还将提供详细但简洁的部署文档(例如,部署步骤,需要设置的环境资源等)。

以下是我看到的常见问题导致您所描述的问题类型:

  1. 环境未正确设置(例如,缺少环境变量,数据源等)。
  2. 应用程序未完全部署(例如,未部署数据库架构)。
  3. 操作系统配置的差异(默认字符编码是我最常见的罪魁祸首)。
  4. 大多数情况下,可以通过日志内容识别这些问题。

答案 15 :(得分:0)

尚未提及,但“定向代码审核”是一个很好的解决方案,特别是如果您在发布之前没有进行适当的审核(每100行代码至少1小时)。

我还看到了令人印象深刻的AppSight Suite演示,它基本上是一种高级环境监控和日志记录工具。它允许客户在一个广泛但相当紧凑的日志文件中记录他的机器上发生的事情,然后您可以重放该文件。

答案 16 :(得分:0)

然而,一个不可重复的问题是艰难的 - 我们仍然可以采用结构化和战略性的方法来解决它们 - 我可以通过经验说,它需要在50%的情况下开箱即用。一般来说,可以将问题分类为不同类型,这有助于识别要使用的工具。例如,如果您有不可重现的应用程序崩溃问题或内存问题,您可以使用分析器并确定特定功能中引起的问题。

此外,最重要的方法之一是信息丰富的日志记录。我还使用了很多枚举来描述过程的状态,具体取决于相关场景。例如,我使用了启动,触发,运行,等待修复等来描述时间表状态并在不同阶段将它们保存到数据库。

答案 17 :(得分:0)

只是一个简短的轶事(因此是'社区维基'):上周我认为在Django应用程序中导入模块pprint以便仅打印Python数据 是一个聪明的主意如果DEBUG是真的:

if settings.DEBUG:
    from pprint import pprint

然后我在这里使用pprint命令作为调试语句:

pprint(somevar) # show somevar on the console

完成工作后,我通过设置DEBUG=False测试了应用。您可以猜到发生了什么:该网站在整个地方都出现了HTTP500错误,我不知道为什么,因为如果DEBUGFalse,则没有追溯。我很困惑,如果我切换回调试模式,错误就会神奇地消失。

我花了1-2个小时在代码中放置print语句,发现代码完全崩溃在上面的pprint()行。然后又花了我半个小时来说服自己不要把头撞在桌子上。

现在讲述了这个故事的道德:

  1. 并非所有看起来像第一个视图中的聪明主意的东西最终都是如此精明。

  2. 调试这些错误的重点是所有配置选项和平台交换机您的代码本身。这可能远远超过一些用户偏好。记录好,如果你对用户的平台做出假设(例如,如果你只测试Win / Mac / Linux,你的代码会在BSD或Solaris上崩溃吗?)

  3. 干杯,

答案 18 :(得分:0)

它非常复杂的问题。我在考虑为此编写一些程序。我刚刚为这个不可重现的bug做了一些程序。它可能会有所帮助

当Bug被赋予..有可能发生几个因素。

我确定所有错误都是可重现的。我一直关注这类问题。

  1. 获取系统信息
  2. 之前客户做过的其他流程。
  3. 发生的时间段。 <罕见或频繁
  4. 它的下一个动作发生在问题之后(它总是相同或不同)
  5. 找出此错误的因素(作为开发人员)
  6. 找出发生此问题的确切位置。
  7. 查找当时的所有系统因素
  8. 检查代码中的所有内存泄漏或用户错误问题或错误情况
  9. 列出所有可能导致此问题的因素。
  10. 每个因素如何影响这个和wat是数据保持这些因素
  11. 检查记忆发生的问题
  12. 检查客户是否有像您这样的当前更新代码
  13. 检查至少1个月的所有日志,发现任何正常的操作都发生了。保持记录

答案 19 :(得分:0)

根据您可以获得WinDbg转储的问题,他们通常会很好地了解发生了什么。我们已经诊断出很多未从小型飞机坠毁的问题。

对于.Net应用程序,我们也是Trace.Writeline,然后我们可以让用户启动DbgView并将输出发送给我们。

答案 20 :(得分:0)

我最近一直在调查这个问题。在我的运营商的过程中,我了解到,虽然计算机系统可能很复杂,但它们是可预测的,因此有信心可以找到问题所在。我对这些问题的解决方法有两个方面:

1)从客户那里收集尽可能多的关于他们失败的详细信息,并对模式进行细致的分析。为多次故障发生收集多组数据,以建立更清晰的图像。

2)尝试并重现内部故障。继续使您的系统越来越类似于客户系统,直到您可以重现它,系统相同或者使它更相似变得不切实际。

这样做时考虑:

1)该系统与其他工作系统之间存在差异。

2)您的产品或导致问题开始发生的客户配置最近发生了哪些变化。

此致

答案 21 :(得分:0)

我经常没有这个问题,但如果我这样做,我会使用屏幕共享或录制的应用程序来观察用户的行动,而不必去那里(除非,正如你所说,它是温暖和阳光的公司支付旅行费用。)