理想的代码与日志记录比率是多少?我不习惯写日志,因为我开发的大多数应用程序都没有太多的日志记录。
最近虽然我换了工作,但我注意到您看不到调用 log4net 的应用程序代码。我很欣赏这很有用,但肯定有太多的调试语句和没有任何调试语句一样糟糕?
有一些日志语句会告诉您每个方法何时开始和结束以及它们返回的内容。当几乎所有事情都完成时。
使用反射在编译时添加日志语句的插件会不会更容易,这样它们就不会在您尝试查看代码时妨碍您?
同样在这些强大的 IDE 和远程调试的日子里,这么多的日志记录真的需要吗?
理想的代码与日志记录比率是多少?我不习惯写日志,因为我开发的大多数应用程序都没有太多的日志记录。
最近虽然我换了工作,但我注意到您看不到调用 log4net 的应用程序代码。我很欣赏这很有用,但肯定有太多的调试语句和没有任何调试语句一样糟糕?
有一些日志语句会告诉您每个方法何时开始和结束以及它们返回的内容。当几乎所有事情都完成时。
使用反射在编译时添加日志语句的插件会不会更容易,这样它们就不会在您尝试查看代码时妨碍您?
同样在这些强大的 IDE 和远程调试的日子里,这么多的日志记录真的需要吗?
由于 log4net 在不堵塞资源方面做得很好,所以我倾向于在日志记录方面有点冗长,因为当您必须更改为调试模式时,您拥有的信息越多越好。这是我通常记录的内容:
调试级别
信息级别
错误级别
致命级别
还有很多日志记录详细信息使我无法询问用户在收到错误消息时他们在做什么。我可以很容易地把它拼凑起来。
完整的日志文件非常有用。考虑一种情况,您的应用程序部署在银行之类的地方。你不能进去手动调试它,他们肯定不会向你发送他们的数据。您可以获得的是一个完整的日志,它可以指出问题发生的位置。拥有多个日志级别非常有帮助。通常,应用程序会以仅报告致命错误或严重错误的模式运行。当您需要对其进行调试时,用户可以打开调试或跟踪输出并获得更多信息。
您看到的那种日志记录似乎确实过多,但如果不了解有关应用程序及其可能部署的位置的更多信息,我真的不能肯定地说这是肯定的。
同样在这些强大的 IDE 和远程调试的日子里,这么多的日志记录真的需要吗?
是的,当然,尽管许多不熟练的开发人员犯的错误是尝试使用错误的方法修复错误,通常倾向于在应该调试时进行日志记录。每个都有一个地方,但至少有几个领域几乎总是需要记录:
// 现在打开数据文件
fp = fopen("data.bin", "rb");
上面的注释可以很容易地放在日志调用中:
const char *kDataFile = "data.bin";
log("现在打开数据文件 %s", kDataFile);
fp = fopen(kDataFile, "rb");
也就是说,您在某些方面是正确的。将日志记录机制用作美化的堆栈跟踪记录器将生成质量非常差的日志文件,因为它没有为开发人员提供足够有用的故障点来检查。所以这里的关键显然是正确和谨慎地使用日志调用,我认为这归结为开发人员的自由裁量权。您需要考虑到您实际上是在为自己制作日志文件;您的用户并不关心它们,并且通常无论如何都会严重误解他们的内容,但您至少可以使用它们来确定您的程序行为不端的原因。
此外,日志文件很少会指出某个错误的直接来源。根据我的经验,它通常会提供一些关于如何复制错误的见解,然后通过复制或调试它的过程来找到问题的原因。
正如您所说,实际上有一个不错的库可以在事后添加日志记录PostSharp。它允许您通过基于属性的编程来完成它,以及许多其他非常有用的东西,而不仅仅是日志记录。
我同意你所说的日志记录有点过分。
其他一些提出了一些优点,尤其是银行场景和其他关键任务应用程序。极端日志记录可能需要它,或者至少能够在需要时打开和关闭它,或者设置各种级别。
不需要那么多的日志记录。没有理由(在生产中)知道每种方法何时开始和结束。也许您在某些方法上需要它,但是日志文件中有这么多噪音使得它们几乎不可能有效地分析。
当重要事情发生时,您应该记录,例如错误、用户登录(审计日志)、事务开始、重要数据更新......等等。如果您有无法从日志中找出的问题,那么您可以在必要时添加更多内容……但仅限于必要时。
此外,仅供参考,在编译时添加登录将是所谓的面向方面编程的一个示例。日志记录将是“横切关注点”。
我认为“日志与代码的比率”是对问题的误解。
在我的工作中,我偶尔会遇到这样一种情况,即 Java 程序中的错误无法在生产环境之外重现,并且客户不希望它再次发生。
然后,您可以用来修复错误的所有信息,就是您自己放入日志文件中的信息。没有调试会话(无论如何在生产环境中都是禁止的) - 没有戳输入数据 - 什么都没有!
因此,日志是您回到错误发生时的时间机器,并且由于您无法提前预测修复未知错误所需的信息 - 否则您可以首先修复错误 - 您需要记录很多东西...
确切的内容取决于场景,但基本上足以确保您永远不会怀疑发生了什么:)
自然这意味着会发生大量的日志记录。然后,您将创建两个日志 - 一个包含仅保留足够长的时间以确保您不需要它的所有内容,另一个包含可以保留更长时间的重要信息。
忽略日志记录过多,通常是由那些不必修复错误而没有其他事情可做的人完成的:)
当您在应用程序的 beta 版本中遇到错误并且无法重现它时,您知道您应该进行过多的日志记录。同样,如果客户报告了错误但您无法重现它,那么过多的日志记录功能可以节省一天的时间。
当您有一个客户场景(即,您无法物理访问其机器的人)时,“太多日志记录”的唯一事情是重新绘制函数以及它们调用的几乎任何东西(应该几乎什么都没有)。或者在操作期间每秒调用 100 次的其他函数(程序启动是可以的,但是,记录 100 次对 get/set 例程的调用,因为根据我的经验,这是大多数问题的根源)。
否则,当您错过一些可以明确告诉您用户机器上的问题所在的关键日志点时,您只会自责。
(注意:这里我指的是为面向开发人员的日志启用跟踪模式时发生的日志记录,而不是面向用户的正常操作日志。)
我个人认为,首先没有硬性规定。我有一些应用程序记录了很多,进出方法,以及通过中间的状态更新。这些应用程序虽然是计划进程,但无需手动运行,并且日志由另一个存储成功/失败的应用程序解析。
我发现实际上,许多用户应用程序不需要大量的日志记录,因为如果真的出现问题,您将通过调试来跟踪那里的值。此外,您通常不需要记录日志的费用。
但是,这实际上取决于项目。
默认情况下,其中有多少行正在记录?我在一个非常像你描述的系统上工作过 - 如果日志记录被加速,只需启动它就会导致超过 20MB 的日志被写入,但即使调试我们也没有为所有模块完全打开它. 默认情况下,它会记录输入代码模块和主要系统事件的时间。它非常适合调试,因为 QA 可以将日志附加到票证上,即使它不可重现,您也可以看到问题发生时发生的情况。如果您正在处理严重的多线程,那么日志记录仍然比我使用过的任何 IDE 或调试器都要好。
在我的工作中,我编写了很多 Windows 服务。对我来说,伐木不是奢侈品。它实际上是我唯一的用户界面。当我们部署到生产环境时,我们无法进行调试,甚至无法访问我们的服务写入的数据库,如果没有日志记录,我们将无法了解出现的任何问题的细节。
话虽如此,我确实相信简洁的日志记录风格是最好的方法。日志消息往往仅限于应用程序的业务逻辑,例如“从帐户 xxx 收到消息”而不是“输入函数 yyy”。我们会记录异常、线程启动、环境设置和时间的回显。除此之外,我们希望调试器在开发和 QA 阶段识别逻辑错误。
我发现自从我开始使用 TDD 以来,日志记录的必要性要小得多。它使确定错误所在的位置变得更加容易。但是,我发现日志语句可以帮助理解代码中发生了什么。当然,调试器可以帮助您对正在发生的事情有一个低层次的了解。但是,如果我想从高层次上了解正在发生的事情,我可以将一行输出与一行代码匹配起来,这样会更容易。
但是,我应该添加的一件事是:确保您的日志语句包含日志语句所在的模块!我无法计算我不得不返回并找到日志语句的实际位置的次数。
我必须承认,当开始编程时,我或多或少地记录了“Dillie-O”所描述的所有细节。
相信我……它在生产部署的最初几天帮助很大,我们严重依赖日志文件来解决数百个问题。
一旦系统变得稳定,我慢慢开始删除日志条目,因为它们的附加值开始减少。(当时没有Log4j 。)
我认为,代码与日志条目的比例取决于项目和环境,它不必是一个恒定的比例。
如今,我们在使用 Log4j 等包进行日志记录、动态启用日志级别等方面具有很大的灵活性。
但是如果程序员没有正确使用它,例如何时使用,何时不使用 INFO、DEBUG、ERROR 等以及日志消息中的详细信息(我见过类似的日志消息,“Hello X, Hello XX,你好,XXX等”只有程序员才能理解)比例将继续保持较高的投资回报率。
我认为另一个因素是正在使用的工具集/平台以及随之而来的约定。例如,日志记录在 J(2)EE 世界中似乎非常普遍,而我不记得曾经在 Ruby on Rails 应用程序中编写过日志语句。