我目前正在开发一个相当大的多层应用程序,该应用程序将部署在海外。虽然我希望它一旦解散就不会倒下或炸毁,但我不能 100% 确定这一点。因此,很高兴知道我可以请求日志文件,以准确找出问题所在以及原因。
所以基本上正如标题所示,我想知道何时以及记录什么?我想知道这一点,以确保我有全面的日志文件,可以轻松检查以确定我的应用程序崩溃时发生的情况。
我目前正在开发一个相当大的多层应用程序,该应用程序将部署在海外。虽然我希望它一旦解散就不会倒下或炸毁,但我不能 100% 确定这一点。因此,很高兴知道我可以请求日志文件,以准确找出问题所在以及原因。
所以基本上正如标题所示,我想知道何时以及记录什么?我想知道这一点,以确保我有全面的日志文件,可以轻松检查以确定我的应用程序崩溃时发生的情况。
1 - 制作一个具有标准化格式的日志。它是什么并不重要,但要确保每个条目都具有相同的基本字段。只是调用“printf”可能不会削减它(替换 System.err.println 或任何适当的)
2 - 允许至少一个字段是任意字符串...开发人员会比您更了解需要存在的内容。
3 - 在每个条目上包含一个高分辨率时间戳。你最终会需要它,相信我。
4 - 如果可能,包括错误来源的文件和行号。这在 C 中很容易,而在 Java 中则有点痛苦。但它在以后非常有用,尤其是当人们开始剪切+粘贴代码时,包括错误消息。
5 - 确保日志位于任何级别的代码都可以使用它的位置。
6 - 我经常使用“Primary”和“Secondary”错误标签,其中“Primary”表示“我是检测到问题的人”,“Secondary”表示“我调用了一个报告错误的函数”。这样可以很容易地找到问题的根源(“Primary: file not found”)并且仍然报告错误的含义(“Secondary: can't load tracking table”)。
7 - 包括一些记录非错误和错误的功能。
我发现最困难的部分是错误不一定是错误。如果您使用文件调用函数,并且该文件不存在,那么是否应该记录一个错误?有时它是一个严重的失败,有时它是意料之中的。这几乎取决于函数的 API;如果函数有办法返回错误,我通常会让它在不记录的情况下这样做;那么更高级别代码的工作就是决定是否需要报告该错误或是否需要报告。
首先,给自己一个日志框架——你没有提到任何特定的语言,但是任何基于 Apache log4j 的框架都是一个安全的选择。最重要的是该框架支持不同级别的详细信息(调试消息、警告、错误消息)。您可以在运行时配置记录器,以确定它将实际写入哪些消息,以及写入到哪里——重新发明轮子来处理记录是没有意义的。
在源代码中实现您的日志框架。作为最低要求,您应该记录并为您的应用程序中可能发生的异常“增加价值”。将堆栈跟踪写入日志文件非常好,但很少能够诊断问题 - 考虑在 catch {} 中记录诸如方法参数值之类的内容。
在更高的级别上,您可以利用不同级别的详细程度来记录它在您的应用程序中发生的事情。如果错误仅发生在无法附加远程调试器的生产系统上,这尤其有用 - 您只需增加日志框架配置文件中的详细级别,并观察所有调试(“使用参数调用方法 X Y") 消息出现在日志中。
我只想补充一点,对于一个大型任务关键型应用程序,一旦部署,问题只能通过客户端发送的日志进行调查,随着时间的推移,对何时何地进行日志记录的良好感觉是应用程序成熟(成熟度与应用程序在一个地方部署和使用的时间量直接相关,以及它在不同客户端/位置的不同部署数量)。
只要您不必为性能付出太多,日志记录就很重要。
根据我的经验,您要记录的最重要的事情是那些警告、糟糕的、健全性检查失败、雨天场景等,在编写晴天场景时往往会忽略它们,有时会用打印“我们不应该到这里”等。这些东西倾向于在测试期间不出现,但在部署期间开始弹出,当然不会被捕获。
如果您记录并打算通过远程读取结果,请确保捕获确切的时间戳、位置和某种会话 ID(以防多个实例同时运行并写入日志文件)。您越容易确定哪些消息是一次执行的一部分,您就越好。
错误级别和类型也很重要。进行搜索以确保您没有从多个位置编写相同的消息也很重要,否则跟踪将很困难。
最后,如果您的用户运行 Mac OS X,请格外小心记录错误:出于某种奇怪的原因,即使在 Leopard 中,默认记录机制的处理成本也很高,并且会占用大量 CPU。
我们开发了一个基于电话的大型系统,该系统在世界各地使用,并且多年来一直使用我们自己的日志记录系统进行应用。调试级别非常重要,我们的应用程序附带的调试设置为“仅错误”,除了对时间最敏感的之外,所有的都启用了日志到文件。我们还支持将我们的输出转移到调试跟踪系统(这是 Windows,所以它是对 OutputDebugString 的简单调用,我们的工程师可以访问一个名为 DBWIN32 的调试捕获器)。这很重要,因为某些类别的错误要求您能够查看多个应用程序的输出,并进行序列化。通过应用这种技术,我已经解决了一些非常棘手的多应用交互错误。应用程序通常会在输出中添加一个人类可读的标签,这样我们就可以在这种情况下判断哪一行来自哪个应用程序。
我们使用的级别通常是:关闭、仅错误、基本、详细、“详细”(其中详细是一个占位符,表示投票结果、用户操作、消息内容等多项内容——作者认为重要的任何内容)。
哦,应用程序写入其日志文件的第一件事是提供其版本资源的标题,因此我们可以知道我们正在处理的构建 - 不要相信用户或本地工程师知道:-)
AOP 对于非侵入式日志记录非常有用。例如,您可以使用 AOP 记录每个方法调用的参数值和返回值,而无需实际将日志记录语句添加到每个方法中。
如何执行此操作的具体细节显然取决于您的目标语言和平台(您没有指定)。有关如何将此类记录器添加到基于 Java Spring 的应用程序的示例,请参见此处。