假如 getName() 方法需要耗费的时间长达 6 秒,那完了!尽管配置文件里的日志级别定义的是 INFO,getName() 方法仍然会倔强地执行 6 秒,完事后再 debug(),这就很崩了!
明明 INFO 的时候 debug() 是不执行的,意味着 getName() 也不需要执行的,偏偏就执行了 6 秒,是不是很傻?
if(logger.isDebugEnabled()) {logger.debug("用户名是:" + getName());
}
换成上面这种方式,那确定此时 getName() 是不执行的,对吧?
为了程序性能上的考量,isDebugEnabled() 就变得很有必要了!假如说 debug() 的时候没有传参,确实是不需要判断 DEBUG 是否启用的。
2)慎重选择日志信息的打印级别,因为这太重要了!如果只能通过日志查看程序发生了什么问题,那必要的信息是必须要打印的,但打印得太多,又会影响到程序的性能。
所以,该 INFO 的 info(),该 DEBUG 的 debug(),不要随便用。
3)使用 Log4j 而不是 System.out、System.err 或者 e.printStackTrace() 来打印日志,原因之前讲过了,就不再赘述了。
4)使用 log4j.properties 文件来配置日志,尽管它不是必须项,使用该文件会让程序变得更灵活,有一种我的地盘我做主的味道。
5)不要忘记在打印日志的时候带上类的全名和线程名,在多线程环境下,这点尤为重要,否则定位问题的时候就太难了。
6)打印日志信息的时候尽量要完整,不要太过于缺省,尤其是在遇到异常或者错误的时候(信息要保留两类:案发现场信息和异常堆栈信息,如果不做处理,通过 throws 关键字往上抛),免得在找问题的时候都是一些无用的日志信息。
7)要对日志信息加以区分,把某一类的日志信息在输出的时候加上前缀,比如说所有数据库级别的日志里添加 DB_LOG,这样的日志非常大的时候可以通过 grep 这样的 Linux 命令快速定位。
8)不要在日志文件中打印密码、银行账号等敏感信息。
06、 总结打印日志真的是一种艺术活,搞不好会严重影响服务器的性能。最可怕的是,记录了日志,但最后发现屁用没有,那简直是苍了个天啊!尤其是在生产环境下,问题没有记录下来,但重现有一定的随机性,到那时候,真的是叫天天不应,叫地地不灵啊!
嗯哼,其实我已经写完了整个日志系统,包括 Log4j、 SLF4J、Logback、Log4j 它弟 Log4j 2,但我觉得分开来发的话,更利于 SEO(瞧我这为了流量的心机,手动狗头)。如果你确实需要看完整版的话,我也贴心地为你准备了,点击下面的链接就可以下载 PDF:
https://pan.baidu.com/s/1dPwsQhT5OMVapE7hGi7vww 提取码:fxxy
码字不易,日常求个赞吧,动一动金手指,bug 少一个(逃。