目的
规范java程序员对于日志的使用规范
背景
首先看下我们现在的项目使用日志的状况
引入的依赖
使用方式
|
|
|
|
可见,我们引入的日志框架很多,然而却基本都没用起来,而且日志打印可读性比较低
日志框架的分类
基于API的日志框架
- slf4j
- common-logging
基于实现的日志框架
- jdk-logging
- log4j
- logback
- log4j 2
各个日志框架的简介
common-logging
common-logging
是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像 log4j
,或者jdk自带的logging
, common-logging
会通过动态查找的机制,在程序运行时自动找出真正使用的日志库。使用它的好处就是,代码依赖是common-logging
而非log4j
, 避免了和具体的日志方案直接耦合。
|
|
动态查找原理
Log 是一个接口声明。LogFactory 的内部会去装载具体的日志系统,并获得实现该Log 接口的实现类。
LogFactory 内部装载日志系统的流程如下:
- 首先,寻找org.apache.commons.logging.LogFactory 属性配置。
- 否则,利用JDK1.3 开始提供的service 发现机制,会扫描classpah 下的META-INF/services/org.apache.commons.logging.LogFactory文件,若找到则装载里面的配置,使用里面的配置。
- 否则,从Classpath 里寻找commons-logging.properties ,找到则根据里面的配置加载。
- 否则,使用默认的配置:如果能找到Log4j 则默认使用log4j 实现,如果没有则使用JDK14Logger 实现,
再没有则使用commons-logging 内部提供的SimpleLog 实现。
从上述加载流程来看,只要引入了log4j 并在classpath 配置了log4j的配置 ,则commons-logging 就会使log4j 使用正常,而代码里不需要依赖任何log4j 的代码。
slf4j
slf4j
全称为Simple Logging Facade for JAVA
,java简单日志门面。类似于Apache Common-Logging
,是对不同日志框架提供的一个门面封装,可以在部署的时候不修改任何配置即可接入一种日志实现方案。但是,他在编译时静态绑定真正的Log库。使用slf4j
时,如果你需要使用某一种日志实现,那么你必须选择正确的slf4j
的jar包的集合(各种桥接包)。
|
|
slf4j静态绑定原理
SLF4J 会在编译时会绑定import org.slf4j.impl.StaticLoggerBinder; 该类里面实现对具体日志方案的绑定接入。任何一种基于slf4j 的实现都要有一个这个类。如:org.slf4j.slf4j-log4j12-1.5.6: 提供对 log4j 的一种适配实现。注意:如果有任意两个实现slf4j 的包同时出现,那么就可能出现问题。
slf4j 与 common-logging 比较
common-logging
通过动态查找的机制,在程序运行时自动找出真正使用的日志库。由于它使用了ClassLoader
寻找和载入底层的日志库, 导致了象OSGI这样的框架无法正常工作,因为OSGI
的不同的插件使用自己的ClassLoader
。 OSGI的这种机制保证了插件互相独立,然而却使Apache Common-Logging
无法工作。
slf4j
在编译时静态绑定真正的Log库,因此可以再OSGI中使用。另外,slf4j
支持参数化的log字符串,避免了之前为了减少字符串拼接的性能损耗而不得不写的if(logger.isDebugEnable())
,现在你可以直接写:logger.debug(“current user is: {}”, user)
。拼装消息被推迟到了它能够确定是不是要显示这条消息的时候,但是获取参数的代价并没有幸免。
log4j
log4j很久没有更新了,现在国外基本是没有开发者用这个框架了,更重要的是原作者也早就已经不再护log4j,推出了logback以及log4j2为了与时俱进,我们也已经抛弃log4j,使用logback或者是log4j2
logback
Logback
,一个“可靠、通用、快速而又灵活的Java日志框架”。logback
当前分成三个模块:logback-core
,logback- classic
和logback-access
。logback-core
是其它两个模块的基础模块。logback-classic
是log4j
的一个改良版本。此外logback-classic
完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j
或JDK Logging
。logback-access
访问模块与Servlet容器集成提供通过Http来访问日志的功能。
选择logback的理由
- logback比log4j要快大约10倍,而且消耗更少的内存。
- logback-classic模块直接实现了SLF4J的接口,所以我们迁移到logback几乎是零开销的。
- logback不仅支持xml格式的配置文件,还支持groovy格式的配置文件。相比之下,Groovy风格的配置文件更加直观,简洁。
- logback-classic能够检测到配置文件的更新,并且自动重新加载配置文件。
- logback能够优雅的从I/O异常中恢复,从而我们不用重新启动应用程序来恢复logger。
- logback能够根据配置文件中设置的上限值,自动删除旧的日志文件。
- logback能够自动压缩日志文件。
- logback能够在配置文件中加入条件判断(if-then-else)。可以避免不同的开发环境(dev、test、uat…)的配置文件的重复。
- logback带来更多的filter。
- logback的stack trace中会包含详细的包信息。
- logback-access和Jetty、Tomcat集成提供了功能强大的HTTP-access日志。
log4j2
log4j2
也是log4j
的作者出的新的一种日志框架,log4j2
在各个方面都与Logback
非常相似,那么为什么我们还需要log4j2
呢?
- 插件式结构。Log4j 2支持插件式结构。我们可以根据自己的需要自行扩展Log4j 2. 我们可以实现自己的appender、logger、filter。
- 配置文件优化。在配置文件中可以引用属性,还可以直接替代或传递到组件。而且支持json格式的配置文件。不像其他的日志框架,它在重新配置的时候不会丢失之前的日志文件。
- Java 5的并发性。Log4j 2利用Java 5中的并发特性支持,尽可能地执行最低层次的加锁。解决了在log4j 1.x中存留的死锁的问题。
- 异步logger。Log4j 2是基于LMAX Disruptor库的。在多线程的场景下,和已有的日志框架相比,异步的logger拥有10倍左右的效率提升。
官方建议一般程序员查看的日志改成异步方式,一些运营日志改成同步。日志异步输出的好处在于,使用单独的进程来执行日志打印的功能,可以提高日志执行效率,减少日志功能对正常业务的影响。
基于以上,java后台日志规范如下:
使用框架
由于slf4j
是编译时静态绑定,同时支持{}
占位符进行日志打印,所以我们最终使用slf4j
与log4j
进行桥接的形式进行日志打印,后期甚至可以升级log4j至logback或者log4j2,就只需要修改下配置文件就OK了
使用规范
pom引入
|
|
日志打印
|
|
打印规范
info日志
|
|
error
|
|