为什么使用log4j2+slf4j?
slf4j(simple logging facade for java)不是一个真正的日志实现,而是一个抽象层( abstraction layer),也可以理解为一个接口,它是一种适配器的实现方式,允许你使用任何一个日志系统,只要修改一些配置即可随时切换底层的日志实现框架(log4j、log4j2、logback)。
log4j2优点:性能更高更稳定。
1. 日志级别
trace:追踪,就是程序推进一下,可以写个trace输出
debug:调试,一般作为最低级别,trace基本不用。
info:输出重要的信息,使用较多
warn:警告,有些信息不是错误信息,但也要给程序员一些提示。
error:错误信息。用的也很多。
fatal:致命错误。级别较高,这种级别不用调试了,重写吧……
机制:如果一条日志信息的级别大于等于配置文件的级别,就记录。
2. 输出源
CONSOLE(输出到控制台)、FILE(输出到文件)等。
3. 布局方式
SimpleLayout:以简单的形式显示
HTMLLayout:以HTML表格显示
PatternLayout:自定义形式显示
在Log4J2中基本采用PatternLayout自定义日志布局。
自定义格式:
%t:线程名称
%p:日志级别
%c:日志消息所在类名
%m:消息内容
%M:输出执行方法
%d:发生时间,%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2011-10-18 22:10:28,921
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%L:代码中的行数
%n:换行
4. 配置文件命名与存储位置
系统选择configuration文件的优先级如下:
classpath下名为 log4j-test.json 或者log4j-test.jsn文件
classpath下名为 log4j2-test.xml
classpath下名为 log4j.json 或者log4j.jsn文件
classpath下名为 log4j2.xml
5、案例:
POM依赖:
<!--日志包--> <!-- slf4j核心包--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <!--核心log4j2jar包--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.8.2</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.8.2</version> </dependency> <!--用于与slf4j保持桥接--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.8.2</version> </dependency> <!--需要使用log4j2的AsyncLogger需要包含disruptor--> <dependency> <groupId>com.lmax</groupId> <artifactId>disruptor</artifactId> <version>3.2.0</version> </dependency>
log4j2.xml内容:
<?xml version="1.0" encoding="UTF-8" ?> <!-- 该xml配置中,xml元素大小写不敏感 --> <!-- status="off",log4j2把自身事件记录到控制台的配置,off表示不记录,其余的记录有trace,debug,info,warn,error,fatal --> <!-- monitorInterval表示检测更改配置的时间,单位是秒,最小间隔为5秒,0或负数表示不检测 --> <!-- service_name 是maven打包传过来的 --> <configuration name="${service_name}-log-config" status="off" monitorInterval="0"> <!-- 常量引用 --> <properties> <property name="LOG_HOME">/home/work/log/${service_name}</property> <property name="FORMAT">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n </property> </properties> <!-- appender用于接收各种日志 --> <appenders> <!-- 常见的输出到console,常用于开发环境中,默认是system_err,还有一个system_out --> <Console name="console" target="system_out"> <!-- 添加过滤器ThresholdFilter,可以有选择的输出某个级别以上的类别 onMatch="ACCEPT" onMismatch="DENY"意思是匹配就接受,否则直接拒绝 --> <thresholdFilter level="info" onMatch="accept" onMismatch="deny"/> <patternLayout pattern="${FORMAT}"/> </Console> <!-- 文件会打印出所有信息,这个log每次程序重新运行会自动清空,由append属性决定,适合临时测试用 --> <!-- append为TRUE表示消息增加到指定文件中,false表示消息覆盖指定的文件内容,默认值是true --> <!-- <File name="testFile" fileName="${LOG_HOME}/test/${service_name}.log" append="false"> <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> </File> --> <RollingFile name="rollingFile" fileName="${LOG_HOME}/${service_name}.log" filePattern="${LOG_HOME}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz"> <PatternLayout pattern="${FORMAT}"/> <Policies> <!-- interval,integer型,指定两次封存动作之间的时间间隔。单位:以日志的命名精度来确定单位,比如yyyy-MM-dd-HH 单位为小时,yyyy-MM-dd-HH-mm 单位为分钟。 --> <!-- modulate,boolean型,说明是否对封存时间进行调制。若modulate=true,则封存时间将以0点为边界进行偏移计算。 --> <!--设置每天打包日志一次--> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!--设置日志文件满10MB后打包--> <SizeBasedTriggeringPolicy size="10 MB"/> </Policies> <DefaultRolloverStrategy max="60"/> </RollingFile> </appenders> <!-- 接收appender --> <loggers> <!-- 3rd Loggers --> <!-- logger中的name是指代码的包名或类名,路径要写全,可以配置不同包中的日志输出到不同的文件中。level是日志输出级别 --> <logger name="java.sql.Connection" level="INFO" additivity="true"> <appender-ref ref="console"/> </logger> <logger name="java.sql.Statement" level="INFO" additivity="true"> <appender-ref ref="console"/> </logger> <logger name="java.sql.PreparedStatement" level="INFO" additivity="true"> <appender-ref ref="console"/> </logger> <logger name="java.sql.ResultSet" level="INFO" additivity="true"> <appender-ref ref="console"/> </logger> <!-- root logger,一般用于放置所有的appender --> <!-- 日志输出级别(>=INFO级别的日志都输出) --> <asyncRoot level="INFO"> <appender-ref ref="console"/> <appender-ref ref="rollingFile"/> <!-- <appender-ref ref="testFile"/> --> </asyncRoot> </loggers> </configuration>