在我工做过的公司里,有一家公司的代码里所有都是日志,而另一家则是一行日志记录都没有。css
可是在线上环境中,日志记录是很是重要的,它能帮咱们快速定位问题所在。整理以后,我发现下面几点关于日志的建议是很是有效的。html
用过 类 Unix 系统的人都知道,Unix 系统的提示哲学是没提示就是最好的提示。若是一个命令执行成功了,那么系统是不会提示的,只有当执行出错的时候才会报错。反观咱们的代码,通常状况下咱们的代码99%都是正常的执行路径,不会出现逻辑异常或代码异常,只有1%的时候才会出现异常。在这种状况下,咱们固然是选择在那1%的地方进行日志输出了。因此写日志咱们应该达成一个共识,那就是:只在逻辑异常或代码异常的地方加上日志提示。java
在咱们讨论“没有提示就是最好的提示”时,咱们只是站在程序猿的角度来思考如何写提示,可是有时候阅读日志的人多是nginx
对于不一样的”谁”,你将要写下的log信息的内容,上下文,类别和level会大不一样。开发者了解程序内部,因此给他的log信息能够比给终端用户的复杂得多。因此为了兼顾其余人对于程序的理解,有时候须要在一些重要的业务逻辑里增长一些与逻辑异常或代码异常无关的一些代码,如:在P2P项目中,当用户完成充值的时候,你须要打印出用户充值成功的信息。数据库
简单地说:咱们不只仅要在逻辑异常或代码异常的地方加上日志提示,并且也须要在每一个环节完成的时候输出日志提示,这样会便于咱们进行线上问题的定位。安全
若是你使用了开源日志框架,那么你要对你程序中每个log语句使用不一样的log级别。其中最困难的一个任务是找出这个log应该是什么级别。在 SLF4J 中经常使用的级别有这么几个,他们的日志级别从高到低是:ERROR > WARN > INFO > DEBUG。当代码中的级别大于设置文件中设置的级别时,对应的日志就会输出。markdown
如下是个人一些建议:多线程
log 输出模式能够帮助咱们在日志中增长一些清晰的上下文信息,不过对添加的信息仍是要多加当心。好比说,若是你是每小时输出一个文件,这样你的日志文件名中已经包含了部分日期时间信息,所以就不必在日志中再包含这些信息。另外在多线程环境下也不要在本身在日志中包含线程名称, 由于这个也能够在模式中配置。框架
根据个人经验, 一个理想的日志模式将包含下列信息:运维
根据实际状况,你还能够添加下面一些信息:
但要记得,不要用反射去本身获取文件名、类名等信息再去做为日志信息输出,这样会极大下降日志效率。若是须要,你完成能够在 SLF4J 的配置文件中进行配置。
若是你的程序被大多数人使用,而你又没有足够的资源作国际化,英语会成为你的不二之选。
没有什么比这样的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 e-mail<a href="mailto:user@domain.com">user@domain.com</a>
又或是:
IndexOutOfBoundsException: index 12 is greater than collection size 10
在上面这一例子中的异常,若是你想把它传播开, 确保在处理的时候带上与当前level相应的上下文,让调试更简单,以下一个 Java 的例子:
public void storeUserRank(int userId,int rank,String game) {
try {
...deal database ...
} catch (DatabaseException de) {
throw new RankingException("Can't store ranking for user "+userId+" in game "+ game + " because " + de.getMessage() );
}
}
使用占位符更有利于代码的阅读,而且能够提升性能。所以你应该写这样的日志记录:
logger.info("User {} login.", userId);
而不是这样的:
logger.info("User " + userId + " login.");
在下面的日志记录中,若是 user 为空,那么将会抛出异常,那么就会直接致使程序中断。
logger.info("User {} login fail.", user.getUserInfo);
所以在日志记录中,要避免日志中发生异常而致使正常的业务逻辑受到影响,这是绝对不容许出现的。
纸上得来终觉浅,说了这么多,但仍是要实践时不断去应用,去提取适合本身的日志规则,这样才能写出好的代码。
出处:http://www.cnblogs.com/chanshuyi/p/how_to_write_log_in_code.html