日志简介和规范 2020-12-21 10:24 > 参考阿里巴巴Java开发者社区 禁止直接使用日志系统(Log4j、Logback)中的API,应当使用接口层面的slf4j的API。 # 常用日志框架 ## j.u.l j.u.l是java.util.logging包的简称,是JDK在1.4版本中引入的Java原生日志框架。Java Logging API提供了七个日志级别来控制输出。分别是:SERVER、WARNING、INFO、CONFIG、FINE、FINER、FINEST。  ## Log4j Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 Log4也有七种日志级别:OFF、FATAL、ERROR、WARN、INFO、DEBUG和TRACE。  ## LogBack LogBack也是一个很成熟的日志框架,其实LogBack和Log4j出自一个人之手,这个人就是Ceki Gülcü。 logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是Log4j的一个改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日记系统如Log4j或j.u.l。logback-access访问模块与Servlet容器集成提供通过Http来访问日记的功能。  ## Log4j2 Log4j2已经不仅仅是Log4j的一个升级版本了,而是从头到尾被重写的,这可以认为这其实就是完全不同的两个框架。 --- 上述四种日志框架, 我们想要在应用中打印日志的时候,可以使用以上四种类库中的任意一种。比如想要使用Log4j,那么只要依赖Log4j的jar包,配置好配置文件并且在代码中使用其API打印日志就可以了。 但是《阿里巴巴Java开发手册》,其中有一条规范做了『强制』要求:  # 日志门面 日志门面,是门面模式的一个典型的应用。 门面模式(Facade Pattern),也称之为外观模式,其核心为:外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。  前面介绍的日志框架,每一种都有他自己单独的API,要使用对于的框架就要使用其API,这就大大增加了应用程序对于日志框架的耦合性。 使用日志门面就是为了屏蔽掉底层日志框架的具体实现,即使以后某天要更换代码的日志框架,只需修改jar包,最多再修改相关日志输出的配置文件就可以了。这就解除了应用和日志框架之间的耦合。 ## SLF4J > SLF4J 的作者就是 Log4j 的作者 Ceki Gülcü Java简易日志门面(Simple Logging Facade for Java,缩写SLF4J),是一套包装Logging 框架的界面程式,以外观模式实现。可以在软件部署的时候决定要使用的 Logging 框架,目前主要支援的有Java Logging API、Log4j及logback等框架。以MIT 授权方式发布。 SLF4J就是一个常用的日志门面,即日志抽象层,并不是真正的日志框架,真正的输出还要依赖具体实现层日志框架(Log4j、logback等)。 ### 优势 - Log4j 提供 **TRACE, DEBUG, INFO, WARN, ERROR** 及 FATAL 六种纪录等级,但是 SLF4J 认为 ERROR 与 FATAL 并没有实质上的差别,所以拿掉了 FATAL 等级,只剩下其他五种。 - 大部分人在程序里面会去写logger.error(exception),其实这个时候Log4j会去把这个exception tostring。真正的写法应该是logger(message.exception);而SLF4J就不会使得程序员犯这个错误。 - 使用SLF4J可以方便的使用其提供的各种集体的实现的jar。(类似commons-logger) - 从commons–logger和Log4j merge非常方便,SLF4J也提供了一个swing的tools来帮助大家完成这个merge。 - SLF4J 只支持 MDC,不支持 NDC。 - Log4j间接的在鼓励程序员使用string相加的写法(这种写法是有性能问题的),而SLF4J提供了字符串内容替换的功能,就不会有这个问题 ,你可以使用logger.error(“{} is+serviceid”,serviceid);。而且这样的写法更有效率,说明如下: ```java //----------Log4j等 // 传统的字符串产生方式,如果没有要记录Debug等级的信息,就会浪费时间在产生不必要的信息上 logger.debug("There are now " + count + " user accounts: " + userAccountList); // 为了避免上述问题,我们可以先检查是不是开启了Debug信息记录功能,只是程序的编码会比较复杂 if (logger.isDebugEnabled()) { logger.debug("There are now " + count + " user accounts: " + userAccountList); } //----------SLF4J // 如果Debug等级没有开启,则不会产生不必要的字符串,同时也能保持程序编码的简洁 logger.debug("There are now {} user accounts: {}", count, userAccountList); ``` ## commons-logging Apache Commons Logging是一个基于Java的日志记录实用程序,是用于日志记录和其他工具包的编程模型。它通过其他一些工具提供API,日志实现和包装器实现。 commons-logging和SLF4J的功能是类似的,主要是用来做日志 门面的。提供更加好友的API工具。  # 总结 在Java生态体系中,围绕着日志,有很多成熟的解决方案。关于日志输出,主要有两类工具。 一类是日志框架,主要用来进行日志的输出的,比如输出到哪个文件,日志格式如何等。 另外一类是日志门面,主要一套通用的API,用来屏蔽各个日志框架之间的差异的。 所以,对于Java工程师来说,关于日志工具的使用,最佳实践就是在应用中使用如Log4j + SLF4J 这样的组合来进行日志输出。 这样做的最大好处,就是业务层的开发不需要关心底层日志框架的实现及细节,在编码的时候也不需要考虑日后更换框架所带来的成本。这也是门面模式所带来的好处。 综上,请不要在你的Java代码中出现任何Log4j等日志框架的API的使用,而是应该直接使用SLF4J这种日志门面。 [几点规范](https://www.cnblogs.com/doit8791/p/8947024.html "几点规范"): - 保证异常捕获日志打印正确,禁止出现捕获异常不做任何处理的行为,不能直接将异常打印到控制台。 - 在线程中run方法做异常捕获并日志输出,避免线程异常日志直接被输出到控制台。 - 使用日志门面slf4j的接口API,而不是使用具体的日志实现框架API。使用占位符打印日志而非用字符串拼接的方式(避免消耗资源)。 - 使用正确的日志级别打印日志,只对严重的程序逻辑异常问题使用error,在程序运行的关键节点输出info日志,在接口函数调用处可打印debug日志。不在生产环境上使用debug日志,更不要在debug日志中输出大对象文件,比如图片文件等。 - 可以在接口调用或给第三方提供的接口中增加额外的日志文件,方便对接问题的排查。可以统一采用AOP模式来打印输出函数接口调用日志。 - 对于线上已存在的频繁打印的无用的调试日志,可以将相应类的日志输出级别调高。避免输出太多无用日志占用存储空间。 - 学习并践行公司内日志处理规范,可以学习阿里开发规约中异常日志规范部分。 --END--
发表评论