Java体系下的日志框架总结

1. 背景说明

用Java做应用程序开发,一定少不了的是日志打印。日志的主要功能包括:

  • 操作记录的审计排查
  • 应用程序逻辑验证,尤其是异常情况下的问题定位
  • 配合其他数据框架,做报表统计、数据分析等。比如通过日志信息回流数仓,加工产出特征。

实际的Java开发中,会引入很多开源的服务框架,比如spring、rpc框架等,这些框架来自不同机构组织,会定义框架自身日志打印规范。Java应用引入框架后,会面临多种日志系统,所以需要统一日志规范的打印格式。举个例子:

我们的应用系统中使用了logback日志系统
系统引用了A.jar,A.jar中使用的日志系统为log4j
系统又引用了B.jar,B.jar中使用的日志系统为slf4j-simple
如果不做日志框架的整合,应用系统就不得不同时支持并维护logback、log4j、slf4j-simple三种日志框架,非常不便。

2、常见的日志框架说明

  • jdk-logging、log4j、logback日志介绍及原理
  • commons-logging与jdk-logging、log4j1、log4j2、logback的集成原理
  • slf4j与jdk-logging、log4j1、log4j2、logback的集成原理
  • slf4j、jcl、jul、log4j1、log4j2、logback大总结

各种jar的功能总结

  • log4j: log4j的全部内容

  • log4j2:

    • log4j-api:log4j2定义的API
    • log4j-core:log4j2上述API的实现
  • logback:

    • logback-core:logback的核心包
    • logback-classic:logback实现了slf4j的API
  • commons-logging: commons-logging的原生全部内容

  • slf4j: 是日志的门面模式,定义了规范的API,没有具体的实现。

  • slf4j 转向某个实际的日志框架:

    • slf4j-jdk14:slf4j到jdk-logging的桥梁
    • slf4j-log4j12:slf4j到log4j的桥梁
    • log4j-slf4j-impl:slf4j到log4j2的桥梁
    • logback-classic:slf4j到logback的桥梁
    • slf4j-jcl:slf4j到commons-logging的桥梁
  • 某个实际的日志框架转向slf4j,slf4j再转向具体的日志框架,做到日志打印框架的统一:

    比如:使用log4j的API进行编程,但是想最终通过logback来进行输出,所以就需要先将log4j的日志输出转交给slf4j来输出,slf4j再交给logback来输出。将log4j的输出转给slf4j,需要log4j-over-slf4j桥接。

    • jul-to-slf4j:jdk-logging到slf4j的桥梁
    • log4j-over-slf4j:log4j到slf4j的桥梁
    • jcl-over-slf4j:commons-logging到slf4j的桥梁

3、slf4j与其它日志框架集成

  • slf4j与jdk-logging集成:

    • slf4j-api
    • slf4j-jdk14(集成包)
  • slf4j与log4j集成:

    • slf4j-api
    • log4j
    • slf4j-log4j12(集成包)
  • slf4j与log4j2集成:

    • slf4j-api
    • log4j-api
    • log4j-core
    • log4j-slf4j-impl(集成包)
  • slf4j与logback集成:

    • slf4j-api
    • logback-core
    • logback-classic(集成包)
  • slf4j与commons-logging集成:

    • slf4j-api
    • commons-logging
    • slf4j-jcl(集成包)

4. 日志系统之间的切换

4.1 log4j无缝切换到logback

在代码中使用了log4j的API来进行日志的输出,现在想不更改已有代码的前提下,使之通过logback来进行实际的日志输出。

已使用的jar包:

  • log4j

使用案例:

private static final Logger logger=Logger.getLogger(Log4jTest.class);

public static void main(String[] args){
	if(logger.isInfoEnabled()){
		logger.info("log4j info message");
	}
}

具体操作如下:

  • 第一步:去掉log4j jar包

  • 第二步:加入以下jar包

    • log4j-over-slf4j(实现log4j切换到slf4j)
    • slf4j-api
    • logback-core
    • logback-classic
  • 第三步:在类路径下加入logback的配置文件

4.2 jdk-logging无缝切换到logback

private static final Logger logger=Logger.getLogger(JulSlf4jLog4jTest.class.getName());

public static void main(String[] args){
	logger.log(Level.INFO,"jul info a msg");
	logger.log(Level.WARNING,"jul waring a msg");
}

上述是使用jdk-logging自带的API来进行编程的,现在我们想这些日志交给logback来输出

解决办法如下:

  • 第一步:加入以下jar包:

    • jul-to-slf4j (实现jdk-logging切换到slf4j)
    • slf4j-api
    • logback-core
    • logback-classic
  • 第二步:在类路径下加入logback的配置文件

  • 第三步:在代码中加入如下代码:

    static{
    	SLF4JBridgeHandler.install();
    }
    

4.3 commons-logging切换到logback

使用的jar包

  • commons-logging

案例如下:

private static Log logger=LogFactory.getLog(JulJclTest.class);

public static void main(String[] args){
	if(logger.isTraceEnabled()){
		logger.trace("commons-logging-jcl trace message");
	}
}	

可以看到我们使用commons-logging的API来进行日志的编程操作,现在想切换成logback来进行日志的输出(这其实就是commons-logging与logback的集成)

解决办法如下:

  • 第一步:去掉commons-logging jar包(其实去不去都无所谓)

  • 第二步:加入以下jar包:

    • jcl-over-slf4j(实现commons-logging切换到slf4j)
    • slf4j-api
    • logback-core
    • logback-classic
  • 第三步:在类路径下加入logback的配置文件

4.4 常用的日志场景切换解释

先来看下slf4j官方的一张图:

Java体系下的日志框架总结_第1张图片

下面通过左上图详细说明案例

  • 现状:目前的应用程序中已经使用了如下混杂方式的API来进行日志的编程, 现在想统一将日志的输出交给logback. 当前日志实现jar:

    • commons-logging
    • log4j
    • jdk-logging
  • 解决办法:

    • 第一步:将上述日志系统全部无缝先切换到slf4j

      • 去掉commons-logging(其实去不去都可以),使用jcl-over-slf4j将commons-logging的底层日志输出切换到slf4j
      • 去掉log4j1(必须去掉),使用log4j-over-slf4j,将log4j1的日志输出切换到slf4j
      • 使用jul-to-slf4j,将jul的日志输出切换到slf4j
    • 第二步:使slf4j选择logback来作为底层日志输出,加入以下jar包:

      • slf4j-api
      • logback-core
      • logback-classic

5. 冲突说明

依据上面介绍的jar的功能,可以理解:

  • jcl-over-slf4j 与 slf4j-jcl 冲突
    • jcl-over-slf4j: commons-logging切换到slf4j

    • slf4j-jcl : slf4j切换到commons-logging

如果这两者共存的话,必然造成相互委托,造成内存溢出

  • log4j-over-slf4j 与 slf4j-log4j12 冲突
    • log4j-over-slf4j : log4j1切换到slf4j
    • slf4j-log4j12 : slf4j切换到log4j1

如果这两者共存的话,必然造成相互委托,造成内存溢出。但是log4j-over-slf4内部做了一个判断,可以防止造成内存溢出:

  • jul-to-slf4j 与 slf4j-jdk14 冲突
    • jul-to-slf4j : jdk-logging切换到slf4j
    • slf4j-jdk14 : slf4j切换到jdk-logging

如果这两者共存的话,必然造成相互委托,造成内存溢出

文章参考:https://my.oschina.net/pingpangkuangmo/blog/410224

你可能感兴趣的:(java,框架技术学习,java,日志框架,日志jar冲突,日志打印)