slf4j为spring boot 的日志功能定义了一套统一的接口,方便各种日志框架去实现。
SLF4J——Simple Logging Facade For Java,它是一个针对于各类Java日志框架的统一Facade抽象。Java日志框架众多——常用的有java.util.logging, log4j, logback,commons-logging, Spring框架使用的是Jakarta Commons Logging API (JCL)。而SLF4J定义了统一的日志抽象接口,而真正的日志实现则是在运行时决定的——它提供了各类日志框架的binding。
spring boot默认使用的日志框架是logback,它的maven jar包名称叫
spring-boot-starter-logging
这里我们谈谈spring boot 整合log4j2日志框架。
当然,logback,log4j和log4j2,肯定都是实现了slf4j接口的日志框架。
这里要注意,之前看其他文章,有人说过spring boot 版本超过1.4,就不再支持log4j了,需要使用log4j2框架。
前言
本文解决以下问题:
- 为何使用log4j2
- springboot下log4j2日志的使用
- 控制台日志显示的级别和文件保存的日志不同
- idea控制台颜色日志的输出
正文
log4j2
目前有关服务器日志输出的框架有很多,如log4j、sl4j和log4j2,为什么我选择使用log4j2呢,看完下面两篇性能的对比,相信你也会选择log4j2
http://www.jianshu.com/p/483a9cf61c36
https://blog.souche.com/logback-log4j-log4j2shi-ce/?utm_source=tuicool&utm_medium=referral
大意就是从不同角度看,log4j2的性能提升比较大。
依赖jar包并解决jar包冲突
需要将springboot内置的日志剃掉,然后引入log4j2,pom如下
<!-- 支持log4j2日志框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
然后需要在resource下面添加log4j2.xml配置文件,当然了如果你不添加,springboo会提示你没有对应文件,并使用默认的配置文件,这个时候级别可以在application.properties中配置
logging.level.root=error
控制台打印结果
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/E:/ide/maven-jar/ch/qos/logback/logback-classic/1.1.11/logback-classic-1.1.11.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/E:/ide/maven-jar/org/apache/logging/log4j/log4j-slf4j-impl/2.7/log4j-slf4j-impl-2.7.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.18.RELEASE)
2019-01-11 16:56:04.582 INFO 7640 --- [ main] com.example.demo.Demo1Application : Starting Demo1Application on 16101281-6 with PID 7640 (E:\ide\workspace\demo-1\target\classes started by Administrator in E:\ide\workspace\demo-1)
2019-01-11 16:56:04.586 INFO 7640 --- [ main] com.example.demo.Demo1Application : No active profile set, falling back to default profiles: default
2019-01-11 16:56:05.038 INFO 7640 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1dd02175: startup date [Fri Jan 11 16:56:05 CST 2019]; root of context hierarchy
2019-01-11 16:56:06.844 INFO 7640 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$76665e5c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-01-11 16:56:07.654 INFO 7640 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 82 (http)
2019-01-11 16:56:07.697 INFO 7640 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-01-11 16:56:07.698 INFO 7640 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.35
注意最上面的几行日志,有警告,原因是项目中同时存在logback和log4j2的依赖包,它们都实现了slf4j接口,所以冲突了。
而logback框架是依赖于spring-boot-starter-logging这个jar包的。这个jar包,你会发现我们pom里面没有主动引入它。但是有jar包依赖了它,maven就会把logging下载到依赖它的jar包中。
我们通过下面的操作,把依赖logging的jar包,找出来,解除它对logging的依赖,同时项目又加入了log4j2的jar包。那么在输出日志的时候,就不会冲突了。
这里我分享一个eclipse的小技巧,如何查看pom.xml里面jar包的关联关系。
打开pom.xml文件,打开Dependency Hierarchy选项卡,将logging这个jar包,输入filter中,就可以看到pom里面谁依赖了它。
我们可以通过eclipse提供的功能,让eclipse帮我们解除pom中的jar包,对logging这个包的依赖
右键spring-boot-strater-logging包,选择项
这时候,我们会发现pom.xml发生了变化:
<!-- 支持JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
关联logback输出日志的jar包,都添加了
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
标签来取消依赖。
重启项目,发现警告没有消失!
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.5.18.RELEASE)
2019-01-11 18:17:16.314 INFO 5272 --- [ main] c.e.d.Demo1Application : Starting Demo1Application on 16101281-6 with PID 5272 (E:\ide\workspace\demo-1\target\classes started by Administrator in E:\ide\workspace\demo-1)
2019-01-11 18:17:16.322 INFO 5272 --- [ main] c.e.d.Demo1Application : No active profile set, falling back to default profiles: default
2019-01-11 18:17:16.676 INFO 5272 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@3eb25e1a: startup date [Fri Jan 11 18:17:16 CST 2019]; root of context hierarchy
2019-01-11 18:17:18.258 INFO 5272 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$6c96c533] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-01-11 18:17:18.954 INFO 5272 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 82 (http)
使用log4j2配置文件
主要结构,和我们用到的大致如下
我们来看一篇复杂的log4j2配置:
<?xml version="1.0" encoding="UTF-8"?>
<!--
日志级别
trace: 是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出。
debug: 调试么,我一般就只用这个作为最低级别,trace压根不用。是在没办法就用eclipse或者idea的debug功能就好了么。
info: 输出一下你感兴趣的或者重要的信息,这个用的最多了。
warn: 有些信息不是错误信息,但是也要给程序员的一些提示,类似于eclipse中代码的验证不是有error 和warn(不算错误但是也请注意,比如以下depressed的方法)。
error: 错误信息。用的也比较多。
fatal: 级别比较高了。重大错误,这种级别你可以直接停止程序了,是不应该出现的错误么!不用那么紧张,其实就是一个程度的问题。
-->
<Configuration status="OFF">
<!-- 定义日志存放目录 -->
<properties>
<property name="logPath">logs</property>
<!-- 输出日志的格式 -->
<!--
%d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间
%p : 日志输出格式
%c : logger的名称
%m : 日志内容,即 logger.info("message")
%n : 换行符
%C : Java类名
%L : 日志输出所在行数
%M : 日志输出所在方法名
hostName : 本地机器名
hostAddress : 本地ip地址 -->
<property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} %L %M - %msg%xEx%n</property>
</properties>
<!--先定义所有的appender(输出器) -->
<Appenders>
<!--输出到控制台 -->
<Console name="ConsoleLog" target="SYSTEM_OUT">
<!--只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY" />
<!--输出日志的格式,引用自定义模板 PATTERN -->
<PatternLayout pattern="${PATTERN}" />
</Console>
<!--输出到文件 -->
<!--文件会打印出所有信息,这个log每次运行程序会自动清空,由append属性决定,这个也挺有用的,适合临时测试用 -->
<!--append为TRUE表示消息增加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true -->
<File name="TestLog" fileName="${logPath}/test.log" append="false">
<PatternLayout pattern="${PATTERN}" />
</File>
<!-- 把error等级记录到文件 一般不用 -->
<File name="FileLog" fileName="${logPath}/error.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
<PatternLayout pattern="${PATTERN}" />
</File>
<!--输出到循环日志,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
<RollingFile name="RollingFileLog" fileName="${logPath}/app.log" filePattern="${logPath}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
<PatternLayout pattern="${PATTERN}" />
<SizeBasedTriggeringPolicy size="10MB" />
</RollingFile>
</Appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效 -->
<Loggers>
<!--建立一个默认的Root的logger,记录大于level高于warn的信息,如果这里的level高于Appenders中的,则Appenders中也是以此等级为起点,比如,这里level="fatal",则Appenders中只出现fatal信息 -->
<!-- 生产环境level>=warn -->
<Root level="debug">
<!-- 输出器,可选上面定义的任何项组合,或全选,做到可随意定制 -->
<appender-ref ref="ConsoleLog" />
<appender-ref ref="TestLog" />
<appender-ref ref="FileLog" />
<appender-ref ref="RollingFileLog" />
</Root>
<!-- 第三方日志系统 -->
<!--过滤掉spring和mybatis的一些无用的DEBUG信息,也可以在spring boot 的logging.level.org.springframework=FATAL设置-->
<!-- <logger name="org.springframework" level="INFO"></logger> -->
<!-- <logger name="org.mybatis" level="INFO"></logger> -->
<!-- <logger name="org.apache.http" level="warn" /> -->
</Loggers>
</Configuration>
该配置文件的,参数配置方式,与logback-spring.xml的配置文件,几乎一致。
配置参数详解
1.关于配置文件的名称以及在项目中的存放位置
log4j 2.x版本不再支持像1.x中的.properties后缀的文件配置方式,2.x版本配置文件后缀名只能为".xml",".json"或者".jsn".
系统选择配置文件的优先级(从先到后)如下:
(1).classpath下的名为log4j2-test.json 或者log4j2-test.jsn的文件.
(2).classpath下的名为log4j2-test.xml的文件.
(3).classpath下名为log4j2.json 或者log4j2.jsn的文件.
(4).classpath下名为log4j2.xml的文件.
我们一般默认使用log4j2.xml进行命名。如果本地要测试,可以把log4j2-test.xml放到classpath,而正式环境使用log4j2.xml,则在打包部署的时候不要打包log4j2-test.xml即可。
2.缺省默认配置文件
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
3.配置文件节点解析
(1).根节点Configuration有两个属性:status和monitorinterval,有两个子节点:Appenders和Loggers(表明可以定义多个Appender和Logger).
status用来指定log4j本身的打印日志的级别.
monitorinterval用于指定log4j自动重新配置的监测间隔时间,单位是s,最小是5s.
(2).Appenders节点,常见的有三种子节点:Console、RollingFile、File.
Console节点用来定义输出到控制台的Appender.
name:指定Appender的名字.
target:SYSTEM_OUT 或 SYSTEM_ERR,一般只设置默认:SYSTEM_OUT.
PatternLayout:输出格式,不设置默认为:%m%n.
File节点用来定义输出到指定位置的文件的Appender.
name:指定Appender的名字.
fileName:指定输出日志的目的文件带全路径的文件名.
PatternLayout:输出格式,不设置默认为:%m%n.
RollingFile节点用来定义超过指定大小自动删除旧的创建新的的Appender.
name:指定Appender的名字.
fileName:指定输出日志的目的文件带全路径的文件名.
PatternLayout:输出格式,不设置默认为:%m%n.
filePattern:指定新建日志文件的名称格式.
Policies:指定滚动日志的策略,就是什么时候进行新建日志文件输出日志.
TimeBasedTriggeringPolicy:Policies子节点,基于时间的滚动策略,interval属性用来指定多久滚动一次,默认是1 hour。modulate=true用来调整时间:比如现在是早上3am,interval是4,那么第一次滚动是在4am,接着是8am,12am...而不是7am.
SizeBasedTriggeringPolicy:Policies子节点,基于指定文件大小的滚动策略,size属性用来定义每个日志文件的大小.
DefaultRolloverStrategy:用来指定同一个文件夹下最多有几个日志文件时开始删除最旧的,创建新的(通过max属性)。
(3).Loggers节点,常见的有两种:Root和Logger.
Root节点用来指定项目的根日志,如果没有单独指定Logger,那么就会默认使用该Root日志输出
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
AppenderRef:Root的子节点,用来指定该日志输出到哪个Appender.
Logger节点用来单独指定日志的形式,比如要为指定包下的class指定不同的日志级别等。
level:日志输出级别,共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
name:用来指定该Logger所适用的类或者类所在的包全路径,继承自Root节点.
AppenderRef:Logger的子节点,用来指定该日志输出到哪个Appender,如果没有指定,就会默认继承自Root.如果指定了,那么会在指定的这个Appender和Root的Appender中都会输出,此时我们可以设置Logger的additivity="false"只在自定义的Appender中进行输出。
4.关于日志level
共有8个级别,按照从低到高为:All < Trace < Debug < Info < Warn < Error < Fatal < OFF.
All:最低等级的,用于打开所有日志记录.
Trace:是追踪,就是程序推进以下,你就可以写个trace输出,所以trace应该会特别多,不过没关系,我们可以设置最低日志级别不让他输出.
Debug:指出细粒度信息事件对调试应用程序是非常有帮助的.
Info:消息在粗粒度级别上突出强调应用程序的运行过程.
Warn:输出警告及warn以下级别的日志.
Error:输出错误信息日志.
Fatal:输出每个严重的错误事件将会导致应用程序的退出的日志.
OFF:最高等级的,用于关闭所有日志记录.
程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少。
重点:
划重点:application.properties中配置日志
#要扫描的包记录日志信息
logging.config=classpath:log4j2.xml
# 定义记录某个包内日志的级别,高于等于则记录,可以多个
logging.level.org.springframework=FATAL
在需要的地方使用
mport org.slf4j.Logger;
import org.slf4j.LoggerFactory;
...
private static Logger logger = LoggerFactory.getLogger(xx.class);
...
logger.info("------xxxx-------");
体会
日志的配置,主要体现为
设置日志文件的路劲和名称,
设置日志文件的输出格式,
设置日志文件,在console中,和file中的,输出的日志等级,和扫描的不同的包/类。
设置日志文件的切片维度和保存策略,比如指定日志文件的大小,按天保存,最大保存多少天,最大保存多少MB。
设置是否输出第三方框架的日志,和日志等级。
指定需要输出日志的包/类,和他们的输出等级。