代码与日志记录的比率?
理想的代码与日志记录比率是多少?我不习惯编写日志,因为我开发的大多数应用程序都没有太多日志记录。
尽管最近我换了工作,但我注意到我们看不到log4net调用的应用程序代码。我知道这很有用,但是肯定有太多的调试语句和根本没有调试语句一样糟糕吗?
有日志记录语句可以告诉我们每种方法何时开始和完成以及它们返回什么。当几乎所有事情都完成时。
拥有一些在编译时使用反射来添加日志记录语句的插件会不会更容易,这样它们就不会像我们尝试查看代码时那样妨碍我们了?
如今,在功能强大的IDE和远程调试的今天,是否真的需要很多日志记录?
解决方案
正如我们所说的,PostSharp实际上是一个不错的库,用于添加日志记录。它使我们可以通过基于属性的编程以及除日志之外的许多其他非常有用的功能来执行此操作。
我同意我们所说的内容对于日志记录有些过分。
其他一些则带来了一些好处,尤其是银行业务场景和其他关键任务应用程序。极端日志记录可能是必需的,或者至少可以在需要时将其打开和关闭,或者设置了各种级别。
不需要那么多日志记录。没有理由(在生产中)知道每种方法的开始和结束时间。也许我们在某些方法上需要这样做,但是由于日志文件中包含大量噪声,因此几乎无法对其进行有效分析。
当发生诸如错误,用户登录(审计日志),事务开始,重要数据更新等重要事件时,我们应该记录日志。如果我们无法从日志中找出问题,则可以在必要时向其中添加更多信息……但仅在必要时添加。
同样,仅作为参考,在编译时添加登录将是所谓的面向方面编程的一个示例。伐木将是"跨领域关注"。
我个人认为,首先没有硬性规定。我有一些应用程序可以记录很多,方法的进出记录,以及通过中间的状态更新。这些应用程序虽然是计划的进程,但会运行,并且日志将由另一个存储成功/失败的应用程序解析。
我发现,实际上,许多用户应用程序都不需要大量的日志记录,因为实际上如果出现问题,我们将进行调试以跟踪那里的值。另外,我们通常不需要记录日志的费用。
但是,这实际上取决于项目。
当我们有客户场景时(即我们无法物理访问其计算机的人),唯一"过多记录"的事情就是重绘函数以及函数调用的几乎任何东西(应该几乎什么都没有)。或者其他在操作过程中每秒被调用100次的函数(但是,程序启动可以记录100次调用以获取/设置例程,因为根据我的经验,这是大多数问题的出处)。
否则,当我们错过一些关键日志点时,只会踢自己,这肯定会告诉我们用户计算机上的问题是什么。
(注意:这里我指的是为面向开发人员的日志而不是面向用户的常规操作日志启用跟踪模式时发生的日志记录。)
由于log4net在不阻塞资源方面做得很好,因此我倾向于在日志记录上有些冗长,因为当我们必须更改为调试模式时,信息越多越好。这是我通常记录的内容:
调试级别
- 传递给方法的任何参数
- 我检索的结果集中的任何行计数
- 当传递给方法时,任何可能包含可疑数据的数据行
- 当环境"拼凑在一起"时,任何可能"杂乱无章"的"生成的"文件路径,连接字符串或者其他值。
信息级别
- 方法的开始和结束
- 任何主要循环的开始和结束
- 任何主要案例/切换语句的开头
错误等级
- 处理的异常
- 无效的登录尝试(如果存在安全问题)
- 我截取了要报告的不良数据
致命等级
- 未处理的异常。
另外,还有许多日志记录详细信息使我无法在收到错误消息时询问用户他们在做什么。我可以很容易地拼凑起来。
完整的日志文件非常有用。考虑一下应用程序部署在银行等地方的情况。我们不能在那里手工调试,他们肯定不会向我们发送数据。我们可以获得的是完整的日志,可以将我们指向发生问题的位置。拥有多个日志级别非常有帮助。通常,应用程序将以仅报告致命错误或者严重错误的模式运行。当我们需要调试它时,用户可以打开调试或者跟踪输出并获得更多信息。
我们所看到的日志记录似乎确实过多,但是如果我们不了解有关应用程序及其部署位置的更多信息,我就不能确定地说是肯定的。
我认为另一个因素是所使用的工具集/平台及其附带的约定。例如,日志记录在J(2)EE世界中似乎很普遍,而我不记得曾经在Ruby on Rails应用程序中编写过日志语句。
默认情况下,其中有多少行正在记录日志?我已经在一个系统上进行过工作,就像我们描述的那样,如果启动日志记录的方式启动它,将导致写入超过20MB的日志,但是即使调试,我们也并未针对所有模块将其完全启动。默认情况下,它将在输入代码模块和主要系统事件时记录日志。这对调试非常有用,因为QA可以将日志添加到票证上,即使它不可复制,我们也可以看到问题发生时的情况。如果我们遇到了严重的多线程问题,那么日志记录仍然比我使用过的任何IDE或者调试器都要好。
Also in these days of powerful IDEs and remote debugging is that much logging really nescisary?
是的,绝对可以,尽管许多不熟练的开发人员所犯的错误是试图使用错误的方法来修复错误,通常是在进行调试时倾向于记录日志。每个都有一个地方,但至少在一些地方几乎总是需要记录日志:
- 为了检查实时代码中的问题,在其中暂停调试器会影响计算结果(当然,日志记录会对这样的实时过程中的时序产生轻微影响,但是很大程度上取决于软件)
- 对于发送给可能无法访问调试器的Beta测试人员或者其他同事的构建
- 用于将数据转储到磁盘,这在调试器中可能不容易查看。例如,某些无法正确解析STL结构的IDE。
- 为了让我们对程序的正常流程有"感觉"
- 除了注释之外,为了使代码更具可读性,例如:
// Now open the data file fp = fopen("data.bin", "rb");
上面的注释可以很容易地放在日志记录调用中:
const char *kDataFile = "data.bin"; log("Now opening the data file %s", kDataFile); fp = fopen(kDataFile, "rb");
就是说,我们在某些方面是正确的。使用日志记录机制作为出色的堆栈跟踪记录器会生成质量很差的日志文件,因为它没有提供足够有用的故障点供开发人员检查。因此,这里的关键显然是正确,谨慎地使用日志记录调用,我认为这归结于开发人员的判断力。我们需要考虑的是,我们实际上是在为自己创建日志文件。用户不在乎它们,并且通常无论如何都会严重误解其内容,但是我们可以使用它们至少确定程序行为异常的原因。
另外,很少有日志文件将我们指向某个错误的直接来源。以我的经验,它通常会为我们提供一些有关如何复制错误的见解,然后通过复制错误或者调试错误的过程来找出问题的原因。
当我们在应用程序的Beta版发布期间遇到错误并无法重现该错误时,我们知道应该进行过多的日志记录。如果客户端报告错误,但我们无法重现该错误,则使用相同的方法,过多的日志记录功能可以节省一天的时间。
在我的工作中,我编写了许多Windows服务。对我来说,伐木不是奢侈;它实际上是我唯一的用户界面。当我们部署到生产环境时,我们将无法访问调试甚至服务所写入的数据库,而没有日志记录,我们将无法知道所出现问题的任何具体细节。
话虽如此,我相信简洁的日志记录样式是最好的方法。日志消息往往仅限于应用程序的业务逻辑,例如"从帐户xxx接收的消息"而不是"输入的功能yyy"。我们记录异常,线程启动,环境设置和时间的回显。除此之外,我们期望调试器在开发和QA阶段识别逻辑错误。
我发现自从我开始使用TDD以来,日志记录的必要性就大大降低了。这样可以更轻松地确定错误所在。但是,我发现日志记录语句可以了解代码中正在发生的事情。当然,调试器可以对正在发生的事情有一个低级的了解。但是,如果我想对正在发生的事情有一个高层次的了解,当我可以将输出的一行与代码的一行匹配时,我会发现更加容易。
但是,我要添加的一件事是:确保日志语句包括该日志语句所在的模块!我无法计算必须经过多少次才能找到日志语句实际所在的位置。
我必须承认,在开始编程时,我或者多或者少记录了" Dillie-O"所述的所有详细信息。
相信我...在生产部署的最初几天,它对我们有很大帮助,在此期间,我们严重依赖日志文件来解决数百个问题。
系统稳定后,随着日志条目的增加值逐渐减少,我开始慢慢删除它们。 (在那个时间点没有Log4j。)
我认为,代码与日志条目的比例取决于项目和环境,并且不必是恒定的比例。
如今,我们在使用Log4j等程序包进行日志记录,动态启用日志级别等方面具有很大的灵活性。
但是,如果程序员没有适当地使用它,例如何时使用,何时不使用INFO,DEBUG,ERROR等以及日志消息中的详细信息(我已经看到了诸如" Hello X,Hello XX, " Hello XXX等",只有程序员才能理解),该比率将继续保持较高的水平,而ROI却降低了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我认为"日志与代码的比率"是对该问题的误解。
在我的工作中,我有时会遇到以下情况:Java程序中的错误无法在生产环境之外重现,并且客户不希望它再次发生。
然后,我们所拥有的用于修复该错误的所有东西就是我们自己在日志文件中输入的信息。没有调试会话(无论如何在生产环境中都是禁止的),没有戳输入数据的事情!
因此,日志是我们臭虫发生时的时间机器,并且由于我们无法提前预测要修复此臭虫所需的信息,而未知的信息是我们无法避免的,否则我们可以首先修复该臭虫,而无需大量日志记录。东西...
究竟什么东西取决于场景,但基本上足以确保我们永远不会怀疑在什么情况下会发生什么:)
自然地,这意味着将发生很多日志记录。然后,我们将创建两个日志,一个日志中的所有内容仅保留足够长的时间以确保我们不需要它,另一个日志中的非平凡信息可以保存更长时间。
消除日志记录过多是通常由那些不必修复bug的人完成的:)