我应该在操作之前还是之后记录日志?

29

我正在考虑在操作周围何处写入日志记录。这里有两种不同的风格。第一种是,在操作之前写入日志。

Before:

log.info("Perform operation XXX")
operation()

以下是一种不同的写法,操作完成后再记录日志。

操作完成后:

operation()
log.info("Operation XXX is done.")

使用 before 风格,日志记录描述的是程序现在要做什么。这种风格的优点在于,当出现问题时,开发人员可以轻松检测到,因为他们知道程序正在做什么。但缺点是,如果操作中出现了问题,比如函数调用被阻塞而永远无法返回,你无法通过阅读日志记录来确定操作是否正确完成。

使用 after 风格,则可以确保操作的完成。

当然,我们也可以将这两种风格混合在一起。

log.info("Perform operation XXX")
operation()
log.info("Operation XXX is done.")

但我觉得这种方式有点啰嗦,它会记录重复的日志。那么,我的问题是 - 什么是好的日志记录方式?我想知道你们怎么想。


我喜欢在操作之前记录日志,这样就可以看到尝试了什么。如果某个操作导致异常或其他问题,日志语句可能不会执行,这会使诊断问题变得更加困难。 - kmiklas
4个回答

32

我通常会使用两个不同的日志级别

第一个设置为“debug”级别,第二个设置为“info”级别。这样,在典型的生产机器上只记录正在进行的操作,但我可以打开调试日志并查看在出现错误之前尝试执行了什么。


1
不是要挑剔(这是某人即将挑剔的明显迹象),但我会根据故障的严重程度使用信息警告来表示第二个。有时候你不知道被调用时的上下文,因此无法确定选择警告还是信息;你必须在返回给调用者后记录警告。此外,有些事情失败得如此频繁,以至于它们会用警告淹没您的日志(使严重警告更难以发现);您可能需要考虑是否要完全记录这些故障。 - Scott Smith

3

这完全取决于你想要记录什么。如果你对代码达到执行操作的点感兴趣,那就在此之前记录。如果你想确保操作成功,那就在操作后记录。如果你两者都想要,那就都记录。


1
也许你可以使用类似于 try catch 的东西?这里有一个简单的 Python 示例:
try :
    operation()
    log.info("Operation XXX is done.")
except Exception:
    log.info("Operation xxx Failed")
    raise Exception() # optional : if you want to propagate failure to another try catch statement and/or crash eventually. 

操作将被启动。 如果没有失败(未引发任何异常),则在日志中会得到成功的声明。

如果失败了(通过引发异常,例如磁盘已满或您正在尝试的其他情况),则会捕获异常并得到失败的声明。

日志更有意义。您可以将详细信息保留为单行,并了解操作是否成功。这是最好的选择。

哦,而且您还可以获得一个钩子点,在失败的情况下添加一些要执行的代码。

希望这能帮助到您。


-3

还有一种风格,我在Linux启动脚本和strace中看到过。它具有您的组合风格的优点,但不那么冗长,但您必须确保您的日志记录设施没有进行任何缓冲。我不知道log.info,所以这里是一个使用print的粗略示例:

print "Doing XXX... ",  # Note lack of newline :)
operation()
print "Done."

(由于在大多数情况下,print使用缓冲区,直接使用此示例不会正常工作。您只有在看到“完成”之前才能看到“正在执行XXX”。但是您可以得到一般想法。)

这种风格的另一个缺点是,如果您有多个线程写入同一个日志,事情可能会混乱。


2
我强烈建议不要这样做。如果你想在 operation() 中添加日志记录怎么办?而且,print 会添加一个新行。我知道这只是伪代码,但是使用任何日志库实现起来都不容易。 - Falmarri
没错,你肯定会遇到嵌套问题。至于print,据我所知,在末尾添加逗号可以抑制换行。 - Jander
@Jander “在末尾添加逗号可以抑制换行符”——当然,但是如果operation()记录了任何内容,它将被附加到错误的行。 - Scott Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接