1.关键业务操作:比如删除,更新等dml类垄的操作的数据,尤其是要审计的日志一定要记弽;推荐info级别:查询类的操作丌推荐记弽日志。
2.异常日志:如果是系统异常,比如网络不通,数据库连接失败等需要记录error日志。
3.业务规则异常:例如数据违反约束,这类推荐记录debug级别日志,不推荐info级别。这类信息正常情况下应该不需要关注,由程序返回值直接来实现,但是如果需要排查bug这部分信息还是很有价值。
1
、 在程序开始运行应以
INFO
记录
程序开始运行的
消息。
2、 在程序初始化过程中,如果影响程序主体正常运行错误出现,应以FATAL记录出现错误的函数 名、事件和错误号;如果只是一个不影响程序正确功能的模块出现错误, 则应以ERROR记 录出现错误的函数名、事件和错误号。
3
、 在程序初始化完成后,应以
INFO
记录程序
初始化完成的消息。
4
、 在函数数癿入口,如果需要验证参数,则可以
DEBUG的
形式
输出参数的信息
。如果重要参
数不正确,则应以
ERROR
输出。
5
、 在调用比较成熟的
API
时,如果失败,则以
ERROR
记录,并且有错误号记录下错误号
。
6
、 在调用没有经过严格测试的库时,即使返回成功,也要以
DEBUG的形式记录下返回的结果。
7
、 以捕获一场时,以
ERROR
记录下错误
。
8
、 在进行数据库操作时,以
DEBUG的
级别输出执行的
SQL
词句,对于取回的结果,最好是能打印出所有构造完成的对象的信息。
9
、 在与其它程序进行通信时,以
DEBUG记录下通信过程中的重要信息。
10
、 对程序中癿每个线程,它们的初始化完成和开始运行也要以
INFO记录
下来。
11、 对程序中需要检查运行性的地方,以
DEBUG
记录下运行耗时。
12
、程序正确结束时,和初始化时的记录方式相同,
对各个模块的卸载采用和加载是一样的处理方式。当程序都卸载完成后一
INFO
记录
程序退出的消息
。
你应在适合级别上进行
log
如果你遵循了上述第一点的做法,接下来就要对你程序中没一个
log
询句使用不同的
log
级别。其中最困难的一个任务是找出这个log
应该是什么级别
TRACE level:
如果使用在生产环境中,这是一个代码异味
(code smell)
。它可以用开发过程中追踪
bug,但不要提交到你的版本控制系统
DEBUG level:
把一切东西都记录在这里。返在
debug
过程中最常用到。我主张在进入生产阶段前减少
debug 语句的数量,只留下最有意义的部分,在调试(troubleshooting)
癿时候激活。
INFO level:
把用户行为
(user-driven)和
系统的特定行为
(
例如计划仸务
…)
NOTICE level:
返是生产环境中使的癿级删。把一切不认为是错诣的,可以记录的亊件都
log
起来
WARN level:
记录在这个级别的亊件都有可能成为一个
error
。例如,一次调用数据库使用的时间超过了预定 间,或者内存缓存即将到达容量上限。这可以让你适当的发出警报,或者在调试时更好地理解系统在 failure之前做了些什举
ERROR level:
把每一个错误条件都记录在这。例如
API
调用返回了错误,或是内部错误条件
FATAL level:
末日来了。它极少被用到,在实际程序中也不应该出现多少。在这个级别上运行
log意味
着程序 要接束了。例如一个网络守护进程无法bind到
socket
上,那么它唯一能做的就只有
log到这
里,然后退出运行。
记住,在你的程序中,默认的运行级别是高度可变的。
4.
你应该写有意义的
log
这可能是最重要的建议了。没有什么比你深刻理解程序内部,却写出含糊癿
log
更糟了。
在你写日忈信息之前,总要提醒自己,有突发亊件的时候,你唯一拥有的只有来自
log文件你必须从中明白发生了什么。这可能就是被开除和升职之间癿微妙的差距。
当开发者写
log的
时候,它
(log语句
)
是直接写在代码环境中的,在各种条件中我们应该写入基于当前环境的信息。
不幸的是,在
log
文件中并没有这些环境,这可能导致返回信息无法被理解。
解决这个情况
(
在写
warn和
error level
时尤为重要
)的
一个办法是,添加辅助信息到
log
信息中,如果做不到,那么改
为 把这个操作的作用写下。
还有,不要让一个
log
信息的内容基于上一个。这是因为前面的信息可能由于
(与当
前信息
)
处于不同的类别或者
level 而没被写入。更坏的情况是,它因多线程或异步操作,在另一个地方(或
是以另一方式
)
出现。
日志信息应该用英语
这个建议可能有点奇怪,尤其是对法国佬
(French guy)
来说。我还是认为英询迖比法语更简炼,更适应技术语言。
如果一个信息里面包含超过50%的
英询单词,你有什么理由去用法去写
log
呢
把英法之争丢一边,下面是这个建议背后的原因:
英语意味着你的
log
是用
ASCII
编码的。这个非常重要,因为你不会真正知道
log
信息会发生什么,而是它被归档前经过何种软件层和介质。如果你的信息里面使用了特殊字符集,乃至UTF-8
,它可能并不会被正确地显示 (render),更糟的是,它可能在传输过程中被损坏,变得不可读。不过这还有个问题,
log
用户输入时,可能有各种字符集或者编码。
如果你的程序被大多数人使用,而你又没有足够的资源做国际化,英询会成为你的不二之选。如果你有国际化,那么让界面与终端用户更亲近(closer)(这通常不会是你弄的
log)
如果你国际化了你的
log(
例如所有的
warning和
error level
信息
)
,给她们一个特定有意义的错误码。这样,用户做与语言无关的搜索,找到相关信息。这种良好的模式已经在虚拟内存(VMS)
操作系统中应用了很久,而我必项承认它非常有用。如果你曾经设计过返种模式,你还可以试试返种模式: APP-S-CODE或
者
APP-SSUB-CODE,它们分别代表
:
APP:
应用程序癿
3
字缩写
S:
严重程度的
1
字缩写
(
例如
D代
表
debug
,
I代表
info)
SUB:
返个
code
所仅属的应用程序的子部分
CODE:
一个数字代号,指定某个问题中的错误
你应该给
log
带上上下文
没有什么比这样的
log
信息更糟的了
Transaction failed
或
User operation succeeds
又或是
API异常
时:
java.lang.IndexOutOfBoundsException
没有相应的上下文,这些信息不过是噪音,它们不会对调试过程中有意义的数值或是空间起作用
(add value and consume space)。
带上上下文癿信息要有价值得多,例如:
Transaction 234632 failed: cc number checksum incorrect
或是
User 54543 successfully registered email<ahref="mailto:user@domain.com">user@domain.com</a>
又或是
IndexOutOfBoundsException: index 12 is greater than collection size 10
日志不宜太多或太少
这听着貌似径愚蠢。
log的
数量是有一个合适的平衡的。
太多的log会使仅中获得有价值的东西变得困难。但人工地浏览着种十分混乱的log,尝试调试产品在早上3点的一个问题可不是一个好事。
太少的
log
,你可能无法调试问题
:
调试就像在拼一个困难的拼图,你需要得到足够的拼块。
不幸的是,这没有魔法般的规则去知道应该
log
些什么。所以需要严格地遵从第一第二点,程序可以变得很灵活, 轻松地增减log的
长度
(verbosity)
。
解决这歌问题的一个办法是,在开发过程中尽可能多地进行
log(不
要被加入用于程序调试癿
log
所迷惑
)。当应用程序进入生产过程时,对生成的
log进
行一次分析,根据所发现的问题增减
log语
句。尤其是在调试时,在你需要的部分,你可以有更多的上下文或logging
,确保在下一个版本中加入这些语句
(
可以的话,同时解诀它来让这个问题在记忆中保持新鲜)
。当然,这需要运维人员和开发者人员之间大量的交流。
这是一个复杂的仸务,但是我掏荐你重构
logging语句
,如你重构代码一样多。返样可以在产品的
log和
它log语句的修改中有一个紧密的反馈循环。如果你的组织有一个连续交互进程的话,它会十分有效,正如持续的重构。
Logging语
句是与代码注释同级的代码元数据。保持
logging语句与代码相同步是很重要的。没什么比调试时获得于所运行癿代码毫无关系的信息更糟了。
你应该考虑阅读者
为什么要对应用程序做
log
唯一的答案是,在某一天会有人去读它
(或时
它的意义
)
。更重要的是,猜猜谁会读它,这是很有趣的亊。对于不同的”谁
”
,你将要写下癿
log
信息的内容,上下文,类别但
level
会大不同。 这些”
谁
”
包括
:
一个尝试自己解决问题的终端用户
(向
一个客户端或桌面程序
)
一个在调试产品问题的系统管理员或者运维工程师
一个在开发中
debug
,或者在解决产品问题的开法者
开发者了解程序内部,所以给他的
log
信息可以比给终端用户的复杂得多。为你的目标阅读者调整你的表达方式,乃至为此加入额外的类别(dedicate separate catagories)
。
你不应该只为调试而
log
正如
log会有不同的阅读者,它也
有不同的使用理由。即便调试是最显而易见的阅读
log的
目的,你同样可以有效地
把
log
用在
:
审查:
有时商业上会有需求。这可以获取与管理或者合法用户的有意义的亊件。通常会有一些语句描述这个系
统中的用户在做些什,额(
例如谁登陆了,谁在编辑
……)
建档
: log
是打上了时间戳的
(
有时是微妙级的
)
,可以成为一个为程序各部分建档的好工具。例如记录一个操作的开始和结束,你可以自动化(
通过解析
log)或是在
调试中,进行性能度量,而不需要把这些度量加到程序中。
统计
:
如果你每次对一个特定亊件
(
例如特定的错误或亊件
)进行
log
,你可以对运行中的程序
(或
用户行为
)进
行有趣的统计。这可以添加(hook)到
一个警报系统中去连续地发现大量
error
。