Log4j,Slf4j,Logback三者之间的联系以及区别

最近公司可能需要做一个基于java日志分析系统,要做这样一个系统,首要工作就是要完成日志的收集工作。Java中的日志的主流框架有Log4j,Log4j2,Logback。目前作者所做的大部分项目都是基于以上几个框架来管理我们的日志。这几个框架有一个共同点都脱离不开Sfl4j这个框架。本文作者从以下几个方面带大家了解一下Java中的日志框架。

  1. Slf4jLog4j,Log4j2,Logback的关系是什么?
  2. Log4j,Log4j2,Logback三者之间的区别是啥?
  3. Log4j,Log4j2,Logback三者可以共存嘛?

Slf4jLog4j,Log4j2,Logback的关系是什么

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framework at deployment time.

Java 的简单日志记录外观 (SLF4J) 用作简单的 各种日志记录框架的外观或抽象 (例如.java.util.logging, logback, log4j) 允许最终用户 在部署时插入所需的日志记录框架。

以上是[Slf4j官网]: https://www.slf4j.org/ 的介绍。也就是说Slf4j是一个抽象层的日志框架,它只负责定规范,不负责具体实现。

Log4j,Log4j2,Logback三者之间的区别是啥?

Log4j,Log4j2,Logback都是作为Slf4j的实现框架,毫无疑问它们都是目前流行的优秀的日志实现框架。logback是直接实现的Slf4j。其余两者并不是直接实现的。需要一个转接包。来实现Slf4j。也就是说客户端只管调用Slf4j定义的接口。具体你的系统用的是那套日志框架。开发者是不用具体去关注的。

Log4j

Log4j是笔者最早使用的日志框架,它是Apache的一个开源项目在java中如果要使用Log4j的话,首先要先引入一个核心Java包

log4j

log4j

version

然后在创建一个log4j.properties的配置文件

################################################################################ 
#①配置根Logger,其语法为: 
# 
#log4j.rootLogger = [level],appenderName,appenderName2,... 
#level是日志记录的优先级,分为OFF,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,ALL 
##Log4j建议只使用四个级别,优先级从低到高分别是DEBUG,INFO,WARN,ERROR 
#通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关 
#比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来 
#appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的 
################################################################################ 
################################################################################ 
#②配置日志信息输出目的地Appender,其语法为: 
# 
#log4j.appender.appenderName = fully.qualified.name.of.appender.class 
#log4j.appender.appenderName.optionN = valueN 
# 
#Log4j提供的appender有以下几种: 
#1)org.apache.log4j.ConsoleAppender(输出到控制台) 
#2)org.apache.log4j.FileAppender(输出到文件) 
#3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件) 
#4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件) 
#5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) 
# 
#1)ConsoleAppender选项属性 
# -Threshold = DEBUG:指定日志消息的输出最低层次 
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出 
# -Target = System.err:默认值System.out,输出到控制台(err为红色,out为黑色) 
# 
#2)FileAppender选项属性 
# -Threshold = INFO:指定日志消息的输出最低层次 
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出 
# -File = C:\log4j.log:指定消息输出到C:\log4j.log文件 
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容 
# -Encoding = UTF-8:可以指定文件编码格式 
# 
#3)DailyRollingFileAppender选项属性 
# -Threshold = WARN:指定日志消息的输出最低层次 
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出 
# -File = C:\log4j.log:指定消息输出到C:\log4j.log文件 
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容 
# -DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。还可以按用以下参数: 
#              '.'yyyy-MM:每月 
#              '.'yyyy-ww:每周 
#              '.'yyyy-MM-dd:每天 
#              '.'yyyy-MM-dd-a:每天两次 
#              '.'yyyy-MM-dd-HH:每小时 
#              '.'yyyy-MM-dd-HH-mm:每分钟 
# -Encoding = UTF-8:可以指定文件编码格式 
# 
#4)RollingFileAppender选项属性 
# -Threshold = ERROR:指定日志消息的输出最低层次 
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出 
# -File = C:/log4j.log:指定消息输出到C:/log4j.log文件 
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容 
# -MaxFileSize = 100KB:后缀可以是KB,MB,GB.在日志文件到达该大小时,将会自动滚动.如:log4j.log.1 
# -MaxBackupIndex = 2:指定可以产生的滚动文件的最大数 
# -Encoding = UTF-8:可以指定文件编码格式 
################################################################################ 
################################################################################ 
#③配置日志信息的格式(布局),其语法为: 
# 
#log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class 
#log4j.appender.appenderName.layout.optionN = valueN 
# 
#Log4j提供的layout有以下几种: 
#5)org.apache.log4j.HTMLLayout(以HTML表格形式布局) 
#6)org.apache.log4j.PatternLayout(可以灵活地指定布局模式) 
#7)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) 
#8)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息) 
#9)org.apache.log4j.xml.XMLLayout(以XML形式布局) 
# 
#5)HTMLLayout选项属性 
# -LocationInfo = TRUE:默认值false,输出java文件名称和行号 
# -Title=Struts Log Message:默认值 Log4J Log Messages 
# 
#6)PatternLayout选项属性 
# -ConversionPattern = %m%n:格式化指定的消息(参数意思下面有) 
# 
#9)XMLLayout选项属性 
# -LocationInfo = TRUE:默认值false,输出java文件名称和行号 
# 
#Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下: 
# %m 输出代码中指定的消息 
# %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL 
# %r 输出自应用启动到输出该log信息耗费的毫秒数 
# %c 输出所属的类目,通常就是所在类的全名 
# %t 输出产生该日志事件的线程名 
# %n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n” 
# %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式 
#    如:%d{yyyy年MM月dd日 HH:mm:ss,SSS},输出类似:2012年01月05日 22:10:28,921 
# %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数 
#    如:Testlog.main(TestLog.java:10) 
# %F 输出日志消息产生时所在的文件名称 
# %L 输出代码中的行号 
# %x 输出和当前线程相关联的NDC(嵌套诊断环境),像java servlets多客户多线程的应用中 
# %% 输出一个"%"字符 
# 
# 可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如: 
#  %5c: 输出category名称,最小宽度是5,category<5,默认的情况下右对齐 
#  %-5c:输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格 
#  %.5c:输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不会有空格 
#  %20.30c:category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉 
################################################################################ 
################################################################################ 
#④指定特定包的输出特定的级别 
#log4j.logger.org.springframework=DEBUG 
################################################################################ 
 
#OFF,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB,ALL 
log4j.rootLogger =ALL,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB 
 
#输出到控制台 
log4j.appender.systemOut = org.apache.log4j.ConsoleAppender 
log4j.appender.systemOut.layout = org.apache.log4j.PatternLayout 
log4j.appender.systemOut.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n 
log4j.appender.systemOut.Threshold = DEBUG 
log4j.appender.systemOut.ImmediateFlush = TRUE 
log4j.appender.systemOut.Target = System.out 
 
#输出到文件 
log4j.appender.logFile = org.apache.log4j.FileAppender 
log4j.appender.logFile.layout = org.apache.log4j.PatternLayout 
log4j.appender.logFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n 
log4j.appender.logFile.Threshold = DEBUG 
log4j.appender.logFile.ImmediateFlush = TRUE 
log4j.appender.logFile.Append = TRUE 
log4j.appender.logFile.File = ../Struts2/WebRoot/log/File/log4j_Struts.log 
log4j.appender.logFile.Encoding = UTF-8 
 
#按DatePattern输出到文件 
log4j.appender.logDailyFile = org.apache.log4j.DailyRollingFileAppender 
log4j.appender.logDailyFile.layout = org.apache.log4j.PatternLayout 
log4j.appender.logDailyFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n 
log4j.appender.logDailyFile.Threshold = DEBUG 
log4j.appender.logDailyFile.ImmediateFlush = TRUE 
log4j.appender.logDailyFile.Append = TRUE 
log4j.appender.logDailyFile.File = ../Struts2/WebRoot/log/DailyFile/log4j_Struts 
log4j.appender.logDailyFile.DatePattern = '.'yyyy-MM-dd-HH-mm'.log' 
log4j.appender.logDailyFile.Encoding = UTF-8 
 
#设定文件大小输出到文件 
log4j.appender.logRollingFile = org.apache.log4j.RollingFileAppender 
log4j.appender.logRollingFile.layout = org.apache.log4j.PatternLayout 
log4j.appender.logRollingFile.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/dd HH:mm:ssS}][%l]%n%m%n 
log4j.appender.logRollingFile.Threshold = DEBUG 
log4j.appender.logRollingFile.ImmediateFlush = TRUE 
log4j.appender.logRollingFile.Append = TRUE 
log4j.appender.logRollingFile.File = ../Struts2/WebRoot/log/RollingFile/log4j_Struts.log 
log4j.appender.logRollingFile.MaxFileSize = 1MB 
log4j.appender.logRollingFile.MaxBackupIndex = 10 
log4j.appender.logRollingFile.Encoding = UTF-8 

Log4j是比较元老级的代码了,它的性能跟安全性Log4j2Logback都是没办法比的。Log4jLog4j2是同一个作者,Log4j2就是log4j的一个升级版。

logback

logback是由log4j创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch。它当前分为以下三个模块:

  • logback-core:其它两个模块的基础模块。
  • logback-classic:它是log4j的一个改良版本,同时它完整实现了slf4j API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging。
  • logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能。

默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台。

1.pom依赖

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

<!--引入以上依赖,会自动引入以下jar
	logback-classic.x.x.x.jar
	logback-core.x.x.x.jar
	slf4j-api-x.x.x.jar
-->

注意spring-boot-starter-parent里已集成logback,可直接使用。

2.logback.xml

在工程resources目录下建立logback.xml

1.logback首先会试着查找logback.groovy文件;

2.当没有找到时,继续试着查找logback-test.xml文件;

3.当没有找到时,继续试着查找logback.xml文件;

4.如果仍然没有找到,则使用默认配置(打印到控制台)。

<?xml version="1.0" encoding="UTF-8" ?>

<configuration>


	<conversionRule conversionWord="clr"
		converterClass="org.springframework.boot.logging.logback.ColorConverter" />

	<property name="log.path" value="./klogs" />

	<!-- logger标签中可以定义指定包路径下的logger的输出日志级别,可以用于过滤不想看到的日志 -->
	<logger name="tk.mybatis" level="warn" />
	<logger name="springfox.documentation" level="warn" />
	<logger name="com.kuiren" level="error" />
	<logger name="com.baomidou.mybatisplus.core.MybatisConfiguration" level="warn" />

	<appender name="consoleLog"
		class="ch.qos.logback.core.ConsoleAppender">
		<layout class="ch.qos.logback.classic.PatternLayout">
			<pattern>
				%d [%p] [%t] [%c:%L] : %msg%n
			</pattern>
		</layout>
	</appender>

	<appender name="fileInfoLog"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>WARN</level>
			<onMatch>DENY</onMatch>
			<onMismatch>ACCEPT</onMismatch>
		</filter>
		<encoder>
			<pattern>
				%d [%p] [%t] [%c:%L] : %msg%n
			</pattern>
		</encoder>
		<rollingPolicy
			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<fileNamePattern>${log.path}/info/info_%d.%i.log</fileNamePattern>
			<timeBasedFileNamingAndTriggeringPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
				<maxFileSize>100MB</maxFileSize>
			</timeBasedFileNamingAndTriggeringPolicy>
			<!--日志文件保留天数 -->
			<maxHistory>15</maxHistory>
		</rollingPolicy>
	</appender>


	<appender name="fileWarnLog"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>WARN</level>
		</filter>
		<encoder>
			<pattern>
				%d [%p] [%t] [%c:%L] : %msg%n
			</pattern>
		</encoder>
		<!--滚动策略 -->
		<rollingPolicy
			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<fileNamePattern>${log.path}/warn/warn_%d.%i.log</fileNamePattern>
			<timeBasedFileNamingAndTriggeringPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
				<maxFileSize>100MB</maxFileSize>
			</timeBasedFileNamingAndTriggeringPolicy>
			<!--日志文件保留天数 -->
			<maxHistory>15</maxHistory>
		</rollingPolicy>
	</appender>

	<appender name="fileErrorLog"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>ERROR</level>
		</filter>
		<encoder>
			<pattern>
				%d [%p] [%t] [%c:%L] : %msg%n
			</pattern>
		</encoder>
		<rollingPolicy
			class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<fileNamePattern>${log.path}/error/error_%d.%i.log</fileNamePattern>
			<timeBasedFileNamingAndTriggeringPolicy
				class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
				<maxFileSize>100MB</maxFileSize>
			</timeBasedFileNamingAndTriggeringPolicy>
			<!--日志文件保留天数 -->
			<maxHistory>15</maxHistory>
		</rollingPolicy>
	</appender>

	<root level="info">
		<appender-ref ref="consoleLog" />
		<appender-ref ref="fileInfoLog" />
		<appender-ref ref="fileWarnLog" />
		<appender-ref ref="fileErrorLog" />
	</root>

</configuration>
logback取代log4j的理由

1.更快的实现:Logback的内核重写了,在一些关键执行路径上性能提升10倍以上。而且logback不仅性能提升了,初始化内存加载也更小了。

2.非常充分的测试:Logback经过了几年,数不清小时的测试。Logback的测试完全不同级别的。

3.Logback-classic非常自然实现了SLF4j:Logback-classic实现了SLF4j。在使用SLF4j中,你都感觉不到logback-classic。而且因为logback-classic非常自然地实现了slf4j , 所 以切换到log4j或者其他,非常容易,只需要提供成另一个jar包就OK,根本不需要去动那些通过SLF4JAPI实现的代码。

4.非常充分的文档:官方网站有两百多页的文档。

5.自动重新加载配置文件,当配置文件修改了,Logback-classic能自动重新加载配置文件。扫描过程快且安全,它并不需要另外创建一个扫描线程。这个技术充分保证了应用程序能跑得很欢在JEE环境里面。

6.Lilith是log事件的观察者,和log4j的chainsaw类似。而lilith还能处理大数量的log数据。

7.谨慎的模式和非常友好的恢复,在谨慎模式下,多个FileAppender实例跑在多个JVM下,能 够安全地写道同一个日志文件。RollingFileAppender会有些限制。Logback的FileAppender和它的子类包括 RollingFileAppender能够非常友好地从I/O异常中恢复。

8.配置文件可以处理不同的情况,开发人员经常需要判断不同的Logback配置文件在不同的环境下(开发,测试,生产)。而这些配置文件仅仅只有一些很小的不同,可以通过,来实现,这样一个配置文件就可以适应多个环境。

9.打印更加灵活:Filters(过滤器)有些时候,需要诊断一个问题,需要打出日志。在log4j,只有降低日志级别,不过这样会打出大量的日志,会影响应用性能。在Logback,你可以继续保持那个日志级别而除掉某种特殊情况,如alice这个用户登录,她的日志将打在DEBUG级别而其他用户可以继续打在WARN级别。要实现这个功能只需加4行XML配置。可以参考MDCFIlter 。

10.SiftingAppender(一个非常多功能的Appender):它可以用来分割日志文件根据任何一个给定的运行参数。如,SiftingAppender能够区别日志事件跟进用户的Session,然后每个用户会有一个日志文件。

11.自动压缩已经打出来的log:RollingFileAppender在产生新文件的时候,会自动压缩已经打出来的日志文件。压缩是个异步过程,所以甚至对于大的日志文件,在压缩过程中应用不会受任何影响。

12.堆栈树带有包版本:Logback在打出堆栈树日志时,会带上包的数据。

13.自动去除旧的日志文件:通过设置TimeBasedRollingPolicy或者SizeAndTimeBasedFNATP的maxHistory属性,你可以控制已经产生日志文件的最大数量。如果设置maxHistory 12,那那些log文件超过12个月的都会被自动移除。

Log4j2

Log4j2log4j 1.xlogback的改进版,据说采用了一些新技术(无锁异步等),使得日志的吞吐量、性能比log4j 1.x提高了10倍,并解决了一些死锁的bug,而且配置更加简单灵活。笔者发稿的时间点,Log4j2出现了不少漏洞。如果要升级建议了解清楚。性能越强的框架,漏洞的数量相对来说也是比较多的(比如fastJson)。

Spring Boot集成log4j2

1. pom.xml

Spring Boot默认使用LogBack,但是我们没有看到显示依赖的jar包,其实是因为所在的jar包spring-boot-starter-logging都是作为spring-boot-starter-web或者spring-boot-starter依赖的一部分。

如果这里要使用Log4j2,需要从spring-boot-starter-web中去掉spring-boot-starter-logging依赖,同时显示声明使用Log4j2的依赖jar包,具体如下:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
	<exclusions>
		<!-- 去掉默认配置 -->
		<exclusion>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-logging</artifactId>
		</exclusion>
	</exclusions>
</dependency>

<!-- 引入log4j2依赖 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

2. log4j2.xml

  • 在application.properties中指定log4j2.xml的位置
    logging.config=classpath:log4j2.xml

如果不想在application.properties中指定log4j2.xml的位置,可以把log4j2.xml重命名为log4j2-spring.xml,这样也是可以按照配置打印日志信息的。

  • log4j2.xml简单示例
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <Appenders>
        <Console name="CONSOLE" target="SYSTEM_OUT">
            <PatternLayout charset="UTF-8" pattern="[%-5p] %d %c - %m%n" />
        </Console>

        <File name="File" fileName="logs/file.log">
            <PatternLayout pattern="%m%n" />
        </File>
    </Appenders>

    <Loggers>
        <root level="info">
            <AppenderRef ref="CONSOLE" />
            <AppenderRef ref="File" />
        </root>
    </Loggers>
</configuration>

Log4j,Log4j2,Logback三者可以共存嘛

这三者是不能共存的,笔者遇到过很多次包冲突问题就是由于两种框架之间的包冲突导致的。

废话时间

笔者觉得Slf4j的设计模式真的厉害,大家如果一直不理解面向接口编程。看完后应该多少有点感悟吧。由于Slf4j的优秀设计(官方叫这种开发模式叫门面模式)。客户端这边是无需任何修改的。我只需要去使用其中api即可。具体你框架里用的啥实现框架。客户端根本不需要关注。使用这种方式开发,如果你的系统想升级或者更换日志框架,那么你只需要更换具体实现包即可。

本篇首发于牧码人博客转载请加上此标示。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值