我最近在我的项目代码库中找到了一条日志语句,上面写着"我在这里搜索参数==> =========== 11/30/2008 === 1 ==== 00:00 AM "
您在应用程序中编写好的日志消息时遵循了哪些指导原则?
日志语句中最有用的部分(当然可能是日期和时间除外)是唯一的ID.我们所有的日志条目都以MSG-xxxxx开头,其中xxxxx是一个唯一的整数.此MSG-xxxxx标记始终在源中进行硬编码,从不在资源文件中,因此很容易找回它.它也是文档中非常简单的搜索键.
另外有用的是始终将变量字符串内容括在双引号中以便轻松区分消息本身:
MSG-12345试图打开"myfile.txt",返回错误代码"123 - 找不到文件".
当您尝试使用某些正则表达式从日志中提取信息时,这也会有所帮助.
那个`log'语句看起来更像是一个trace语句.
记录:显示正常事件和错误
跟踪:显示执行路径以及所有日志记录事件
就个人而言,我希望日志记录找出我的程序已经完成了哪些工作,我想要跟踪语句来验证执行路径并找出问题所在.我将跟踪语句路由到一个单独的文件,其中包含两种类型的上下文日志消息.
因此,您至少应该有2个日志级别,并且能够关闭跟踪性能.您应该能够将这些事件流路由到不同的位置.这使您可以轻松地保存日志以获取历史记录,同时不会使用您只想跟踪问题的调试信息混乱.
这里的很多答案都集中在日志消息中包含的字段中,但我认为日志调用的放置和日志记录级别更为重要.如果您使用log4net,您可以通过配置文件随意包含/排除日期戳,但是如果不重新编译,您将无法放置或删除日志语句,因此有必要仔细考虑它们的去向.除了标准字段(例如时间戳和线程ID等)之外,您还想知道进行调用的类和方法名称.如果你按照你所关注的类型命名你的记录器的最佳做法,Log4net等已经处理了类名.除此之外,我通常包括方法名称.这对于跟踪尤为必要,但我将其包含在所有日志消息中.
记录:
您想要了解有关将要执行的操作的足够信息,以便在出现问题时回过头来查看.好的候选人是消息ID,电子邮件地址,以及唯一标识工作项的东西.这种消息应该在这种数据可用时立即出现,这样当你通过日志文件阅读时,你会看到类似"尝试用y做x"的事情,然后如果我们看到异常,我们知道我们需要查看哪个工作项目,以了解我们失败的原因.
记录异常应与"尝试"日志消息配对,以便在读取日志时异常消息在上下文中有意义.这意味着要考虑异常处理的结构.如果你使用.net并且你只想记录一个异常,而不是处理它,你想要重新抛出同一个异常,而不是一个新异常,所以只需要'throw'而不是'throw e',其中'e'是你的例外实例.如果它没有意义,请查看这个.
追踪:
这实际上更简单,通常我会在感兴趣的方法的开头和结尾都有一条消息,比如书挡.在条目中,您可以打印影响程序流的关键方法参数.在方法结束时记录消息是一种可选的,通常你会有兴趣查看类似于堆栈跟踪的跟踪类型.你可以找出没有它们的执行路径.
表现:
对于字符串性能,如果使用log4net或类似的方法,请使用'*Format'方法.这内部将使用StringBuilder,因此您不会一直支付不可变的字符串惩罚.一般来说,关键是能够关闭跟踪以获得性能,并且即使日志消息很昂贵,也要使日志记录足够简洁以便继续使用.正确完成后,应该没有足够的问题.
不要在日志记录语句中进行字符串连接,至少是调试语句.
我刚刚工作的一个Java应用程序性能惨淡.所以我们破解了分析器,看看瓶颈在哪里.事实证明,这主要是由于在嵌套的内部循环等中组装的DEBUG级别日志记录语句所产生的字符串连接操作(哈哈,并认为它们首先被添加以找出性能如此糟糕的原因) !)
不要这样做
LOGGER.debug("The variable was " + myVariable + " and we are doing " + foo);
而是这样做
if (LOGGER.isDebugEnabled()) { LOGGER.debug("put your debug statement here " + foo + " and " + bar); }
有5个方面对我很重要(从不太重要的地方开始):
在日志条目中包括时间戳
提供筛选不太重要的“垃圾邮件”条目的可能性。良好的旧方括号标记对于grep应该足够了。如果其中一些会自动生成,那就很好了-取决于日志类型(消息,警告,声明等)以及可选的消息重要性级别(垃圾邮件,正常,高,严重)。IMO也建议手动添加其他上下文缩小标签。
使日志功能/宏尽可能易于使用。
立即刷新输出缓冲区。
提供即时和明确确定日志条目生成位置(源文件名+行号)的可能性。在某些语言中,这可能很困难,但通常确切地知道哪个断言失败意味着立即修复该错误。此外,您不会浪费时间手动添加日志位置标识符(例如“ SomeClass :: SomeMethod:Message”)