文章目录
1 混而不乱的Java日志体系
1.1 Java日志发展史
- 1999年Ceki推出log4j日志框架,并捐给Apache。Ceki也加入Apache组织。据说Apache基金会还曾经建议Sun引入Log4j到Java的标准库中,但Sun拒绝了。
- 2002年Java1.4发布,Sun推出了自己的日志库JUL(Java Util Logging),其实现基本模仿了Log4j的实现。在JUL出来以前,Log4j就已经成为一项成熟的技术,使得Log4j在选择上占据了一定的优势;
- 2003年Apache推出了JCL(Jakarta Commons Logging)。
JCL
只是定义了一套日志接口(其内部也提供一个Simple Log的简单实现),支持运行时动态加载日志组件的实现,也就是说,在你应用代码里,只需调用Commons Logging的接口,底层实现可以是Log4j,也可以是Java Util Logging; - 2006年,Ceki离开了Apache,回瑞典创建了QOS公司,然后先后创建了Slf4j(日志门面接口,类似于Commons Logging)和Logback(Slf4j的实现)两个项目;
- 2012年,Apache眼看有被Logback反超的势头,于2012-07重写了Log4j 1.x,成立了新的项目Log4j 2,2014年7月其GA版本(正式发布版)发布。
1.2 JUL
Sun公司在 jdk1.4版本增加了一个日志包java.util.logging,简称为jul,用以对抗log4j。
- JUL控制台输出使用
System.err
进行日志输出
-
JUL日志输出级别
日志级别从小到大,分别为:
ALL<FINEST<FINER<FINE<CONFIG<INFO<WARNING<SEVERE<OFF
输出所有:ALL
非常详细: FINEST
较详细: FINER
详细: FINE
配置: CONFIG
信息: INFO
警告: WARNING
严重: SEVERE
所有都不输出:OFF
jul默认日志级别为INFO。默认配置文件在
%JAVA_HOME%/jre/lib/logging.properties
-
使用方式
import java.util.logging.Level; import java.util.logging.Logger; //--------省略其他代码-------- Logger logger=Logger.getLogger(JULService.class.getName()); //方式1 logger.log(Level.FINEST,"FINEST LOG"); //方式2 简写 logger.finest("finest log "); //--------省略其他代码--------
-
配置文件
默认配置文件在
%JAVA_HOME%/jre/lib/logging.properties
1.3 log4j
log4j最后一次更新时间是2012年。apache已不在维护,建议使用log4j2😂
1.3 .1 日志级别
级别 | 描述 |
---|---|
OFF | 最高级别,用于关闭日志记录。 |
FATAL | 导致应用程序提前终止的严重错误。一般这些信息将立即呈现在状态控制台上。 |
ERROR | 其他运行时错误或意外情况。一般这些信息将立即呈现在状态控制台上。 |
WARN | 使用已过时的API,API的滥用,潜在错误,其他不良的或意外的运行时的状况(但不一定是错误的)。一般这些信息将立即呈现在状态控制台上。 |
INFO | 令人感兴趣的运行时事件(启动/关闭)。一般这些信息将立即呈现在状态控制台上,因而要保守使用,并保持到最低限度。 |
DEBUG | 流经系统的详细信息。一般这些信息只记录到日志文件中。 |
TRACE | 最详细的信息。一般这些信息只记录到日志文件中 |
1.3.2 配置文件
-
自定义输出格式说明
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名%m 用于输出与日志记录事件相关联的应用程序提供的消息。
%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。 -
Log4j提供的appender有以下几种:
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) -
log4j.properties 文件
# 把logger和具体的appender关联起来 log4j.rootLogger=INFO,stdout,R,error # stdout 输出到控台 log4j.appender.stdout=org.apache.log4j.ConsoleAppender # 日志输出级别 log4j.appender.stdout.Threshold = TRACE # stdout 输出格式 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout # %d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n # R 输出到文件 (文件大小到达指定尺寸的时候产生一个新的文件) log4j.appender.R=org.apache.log4j.RollingFileAppender log4j.appender.R.File=/log/example.log log4j.appender.R.Append = true # 日志输出级别 log4j.appender.R.Threshold = ERROR # 日志文件最大大小 log4j.appender.R.MaxFileSize=100MB #保留最近的7个日志文件 log4j.appender.R.MaxBackupIndex=7 log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n # 输出到文件,每天产生一个日志文件,不会自动清除日志文件 log4j.logger.error=error log4j.appender.error = org.apache.log4j.DailyRollingFileAppender log4j.appender.error.DatePattern='_'yyyy-MM-dd'.log' log4j.appender.error.File = /log/error.log log4j.appender.error.Append = true # 日志输出级别 log4j.appender.error.Threshold = ERROR log4j.appender.error.layout = org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n log4j.logger.com.warybee=INFO
-
log4j.xml 文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd"> <log4j:configuration > <appender name="stdout" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n "/> </layout> </appender> <!-- 输出到文件 --> <appender name="log4jFile" class="org.apache.log4j.rolling.RollingFileAppender"> <param name="Append" value="true"/> <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy"> <param name="FileNamePattern" value="./log/log_%d{yyyy-MM-dd}.log" /> </rollingPolicy> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} [Thread: %t] %-5p %20c %L:%m %n "/> </layout> <filter class="org.apache.log4j.varia.LevelRangeFilter"> <param name="LevelMin" value="DEBUG"/> <param name="LevelMax" value="DEBUG"/> </filter> </appender> <!-- category(类别)为'org.springframework'的logger只记录level为“info”或更高级别的消息; 即:如果您使用的类名获取logger(如Logger.getLogger(AClass.class)) 而且AClass是org.springframework包的一部分,则它属于这一category --> <logger name="org.springframework"> <level value="info"/> </logger> <root> <!-- 所有日志消息的级别为“debug”或更高的将被记录,除非另有定义 所有日志消息将都记录到appender “stdout”中,除非另有定义 --> <level value="debug" /> <appender-ref ref="stdout" /> <appender-ref ref="log4jFile" /> </root> </log4j:configuration>
-
使用
添加依赖
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency>
package com.warybee.service;
import org.apache.log4j.Logger;
public class Log4jTestService {
private static Logger logger=Logger.getLogger(Log4jTestService.class);
public void test1(){
logger.trace("trace");
logger.debug("logger");
logger.info("info");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
}
}
1.4 JCL
JCL,全称为"Jakarta Commons Logging"。最后一次更新2014年,差不多已经退出历史舞台。
commons-logging的目的是为“所有的Java日志实现”提供一个统一的接口,使项目与日志实现工具解耦,具体的日志实现可以是Log4j,也可以是Java Util Logging
-
添加依赖包
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency>
-
使用
package com.warybee.service; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class JCLService { private static Log log= LogFactory.getLog(JCLService.class); public void test1(){ log.trace("trace"); log.debug("log"); log.info("info"); log.warn("warn"); log.error("error"); log.fatal("fatal"); } }
JCL默认使用JUL(Java Util Logging)进行日志输出
-
commons-logging+log4j
-
添加log4j依赖
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.16</version> </dependency>
-
添加log4j配置文件
参考上一节log4j配置
-
1.5 Slf4j+logback
JAVA简易日志门面(Simple Logging Facade for Java,缩写SLF4J)
1.5.1 依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
1.5.2 使用
package com.warybee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
public class Slf4jService {
final Logger logger = LoggerFactory.getLogger(Slf4jService.class);
public void test1(String name){
logger.info("param is {}",name);
}
}
1.5.3 日志级别
SLF4J相比log4j去除了FATAL
级别。其他与log4j一样
级别 | 描述 |
---|---|
ERROR | 其他运行时错误或意外情况。一般这些信息将立即呈现在状态控制台上。 |
WARN | 使用已过时的API,API的滥用,潜在错误,其他不良的或意外的运行时的状况(但不一定是错误的)。一般这些信息将立即呈现在状态控制台上。 |
INFO | 令人感兴趣的运行时事件(启动/关闭)。一般这些信息将立即呈现在状态控制台上,因而要保守使用,并保持到最低限度。 |
DEBUG | 流经系统的详细信息。一般这些信息只记录到日志文件中。 |
TRACE | 最详细的信息。一般这些信息只记录到日志文件中 |
1.5.4 logback配置文件
① 根节点
包含下面三个属性:
- scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
- scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
- debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false
示例:
<configuration scan="true" scanPeriod="60*1000" debug="true">
<!--省略其他-->
</configuration>
② property
可以用来设置变量,可以通过${name}来访问
示例:
<configuration scan="true" scanPeriod="60*1000" debug="true">
<!--定义日志输出目录-->
<property name="log.path" value="/logs/logback.log" />
</configuration>
③ 子节点 appender
负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名。下面只介绍常见的appder
Ⅰ ConsoleAppender
把日志输出到控制台,有以下子节点
- :对日志进行格式化。
- :字符串System.out(默认)或者System.err
<configuration scan="true" scanPeriod="60" debug="true">
<!--定义日志输出目录-->
<property name="log.path" value="/logs/logback.log" />
<!--输出到控制台-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
Ⅱ FileAppender
把日志添加到文件,有以下子节点
- :被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
- :如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true。
- :对记录事件进行格式化。
- :如果是 true,日志会被安全的写入文件,即使其他的FileAppender也在向此文件做写入操作,效率低,默认是 false。
<configuration scan="true" scanPeriod="60" debug="true">
<!--定义日志输出目录-->
<property name="log.path" value="/logs/logback.log" />
<!--输出到文件-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<append>true</append>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="FILE" />
</root>
</configuration>
Ⅲ RollingFileAppender
滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:
-
:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
-
:如果是 true,日志被追加到文件结尾,如果是 false,清空现存文件,默认是true
-
:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。属性class定义具体的滚动策略类
-
ch.qos.logback.core.rolling.TimeBasedRollingPolicy
最常用的滚动策略,它根据时间来制定滚动策略,有如下子节点:
- 文件名称生成规则,默认格式是 yyyy-MM-dd
- 控制保留的归档文件的最大数量,超出数量就删除旧文件
-
ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy
根据当前活动文件的大小,如果超过指定大小会告知RollingFileAppender 触发当前活动文件滚动。
<configuration scan="true" scanPeriod="60" debug="true">
<!--定义日志输出目录-->
<property name="log.path" value="/logs/logback.log" />
<!--每天生成一个日志文件-->
<appender name="RFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<!--最多保留30天的日志文件-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="debug">
<appender-ref ref="RFILE" />
</root>
</configuration>
④ 子节点 logger
用来设置某一个包或具体的某一个类的日志打印级别、以及指定
包含的属性有:
- name属性:用来指定受此loger约束的某一个包或者具体的某一个类
- level属性:用来设置打印级别,大小写无关:ALL,TRACE, DEBUG, INFO, WARN, ERROR,和OFF, 如果未设置此属性,那么当前loger将会继承上级的级别
- addtivity属性:是否向上级logger传递打印信息。默认是true
- 可以包含零个或多个元素,标识这个appender将会添加到这个logger。
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
⑤ 子节点Root
- level属性:用来设置打印级别,大小写无关:ALL,TRACE, DEBUG, INFO, WARN, ERROR,和OFF, 如果未设置此属性,那么当前loger将会继承上级的级别
- 可以包含零个或多个元素,标识这个appender将会添加到这个logger。
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</root>
⑥ logback配置实例
<configuration scan="true" scanPeriod="60" debug="true">
<!--定义日志输出目录-->
<property name="log.path" value="/logs/logback.log" />
<!--输出到控制台-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
</encoder>
</appender>
<!--输出到文件-->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}</file>
<append>true</append>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
</encoder>
</appender>
<!--每天生成一个日志文件-->
<appender name="RFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/debug.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<!--最多保留30天的日志文件-->
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- All < Trace < Debug < Info < Warn < Error < Fatal < OFF. -->
<root level="Info">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<appender-ref ref="RFILE" />
</root>
</configuration>
1.6 slf4j+log4j2
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<!--slf4j对应log4j2的中间件,即桥接,告诉slf4j使用log4j2-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.14.1</version>
</dependency>
<!--log4j2核心包-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.14.1</version>
</dependency>
log4j2配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration status="WARN">
<Properties> <!-- 配置日志文件输出目录,此配置将日志输出到工程目录下的log4j2_logs文件夹 -->
<Property name="LOG_HOME">
log4j2_logs
</Property>
</Properties>
<Appenders>
<!--这个输出控制台的配置,即System.out -->
<Console name="console_out_appender" target="SYSTEM_OUT">
<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) . -->
<ThresholdFilter level="INFO" onMatch="ACCEPT"
onMismatch="DENY" />
<!-- 输出日志的格式 -->
<PatternLayout pattern="%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n" />
</Console>
<!-- 这个输出控制台的配置,这里输出error级别的信息到System.err -->
<Console name="console_err_appender" target="SYSTEM_ERR">
<ThresholdFilter level="ERROR" onMatch="ACCEPT"
onMismatch="DENY" />
<PatternLayout pattern="%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n" />
</Console>
<!-- TRACE级别日志 ; 设置日志格式并配置日志压缩格式,压缩文件独立放在一个文件夹内, 日期格式不能为冒号,否则无法生成,因为文件名不允许有冒号,此appender只输出trace级别的数据到trace.log -->
<RollingFile name="trace_appender" immediateFlush="true"
fileName="${LOG_HOME}/trace.log" filePattern="${LOG_HOME}/trace/trace - %d{yyyy-MM-dd HH:mm:ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<!-- 每个日志文件最大2MB -->
<SizeBasedTriggeringPolicy size="2MB" />
</Policies>
<Filters>
<!-- 此Filter意思是,只输出TRACE级别的数据 DENY,日志将立即被抛弃不再经过其他过滤器; NEUTRAL,有序列表里的下个过滤器过接着处理日志;
ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
<ThresholdFilter level="debug" onMatch="DENY"
onMismatch="NEUTRAL" />
<ThresholdFilter level="trace" onMatch="ACCEPT"
onMismatch="DENY" />
</Filters>
</RollingFile>
<!-- DEBUG级别日志 设置日志格式并配置日志压缩格式,压缩文件独立放在一个文件夹内, 日期格式不能为冒号,否则无法生成,因为文件名不允许有冒号,此appender只输出debug级别的数据到debug.log; -->
<RollingFile name="debug_appender" immediateFlush="true"
fileName="${LOG_HOME}/debug.log" filePattern="${LOG_HOME}/debug/debug - %d{yyyy-MM-dd HH:mm:ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies><!-- 每个日志文件最大2MB ; -->
<SizeBasedTriggeringPolicy size="2MB" />
<!-- 如果启用此配置,则日志会按文件名生成新压缩文件, 即如果filePattern配置的日期格式为 %d{yyyy-MM-dd HH}
,则每小时生成一个压缩文件, 如果filePattern配置的日期格式为 %d{yyyy-MM-dd} ,则天生成一个压缩文件 -->
<TimeBasedTriggeringPolicy interval="1"
modulate="true" />
</Policies>
<Filters><!-- 此Filter意思是,只输出debug级别的数据 -->
<ThresholdFilter level="info" onMatch="DENY"
onMismatch="NEUTRAL" />
<ThresholdFilter level="debug" onMatch="ACCEPT"
onMismatch="DENY" />
</Filters>
</RollingFile>
<!-- INFO级别日志 -->
<RollingFile name="info_appender" immediateFlush="true"
fileName="${LOG_HOME}/info.log" filePattern="${LOG_HOME}/info/info - %d{yyyy-MM-dd HH:mm:ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="2MB" />
</Policies>
<Filters>
<ThresholdFilter level="warn" onMatch="DENY"
onMismatch="NEUTRAL" />
<ThresholdFilter level="info" onMatch="ACCEPT"
onMismatch="DENY" />
</Filters>
</RollingFile>
<!-- WARN级别日志 -->
<RollingFile name="warn_appender" immediateFlush="true"
fileName="${LOG_HOME}/warn.log" filePattern="${LOG_HOME}/warn/warn - %d{yyyy-MM-dd HH:mm:ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="2MB" />
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="DENY"
onMismatch="NEUTRAL" />
<ThresholdFilter level="warn" onMatch="ACCEPT"
onMismatch="DENY" />
</Filters>
</RollingFile>
<!-- ERROR级别日志 -->
<RollingFile name="error_appender" immediateFlush="true"
fileName="${LOG_HOME}/error.log" filePattern="${LOG_HOME}/error/error - %d{yyyy-MM-dd HH:mm:ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="2MB" />
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT"
onMismatch="DENY" />
</Filters>
</RollingFile>
</Appenders>
<loggers>
<!--使appender生效-->
<!-- 配置日志的根节点 -->
<!-- 定义logger,只有定义了logger并引入了appender,appender才会生效 -->
<root level="trace">
<appender-ref ref="console_out_appender" />
<appender-ref ref="console_err_appender" />
<appender-ref ref="trace_appender" />
<appender-ref ref="debug_appender" />
<appender-ref ref="info_appender" />
<appender-ref ref="warn_appender" />
<appender-ref ref="error_appender" />
</root>
</loggers>
</configuration>
2 统一日志输出
2.1 Slf4j适配器
图片来自官网:http://www.slf4j.org/manual.html
如果你想用slf4j作为日志门面的话,你如何去配合使用其他日志实现组件
- slf4j + logback
slf4j-api.jar
+logback-classic.jar
+logback-core.jar
- slf4j + log4j
slf4j-api.jar
+slf4j-log4j12.jar
+log4j.jar
- slf4j + jul
slf4j-api.jar
+slf4j-jdk14.jar
- 也可以只用slf4j无日志实现
slf4j-api.jar
+slf4j-nop.jar
2.2 Slf4j桥接器
图片来自官网文档:http://www.slf4j.org/legacy.html
-
jcl-over-slf4j.jar
简化从 JCL 到 SLF4J 的迁移
-
log4j-over-slf4j
简化从log4j 到 SLF4J 的迁移
-
jul-over-slf4j.jar
简化从 JUL 到 SLF4J 的迁移
场景应用
自己的应用使用了slf4j+logback,引入的第三方框架使用的是log4j,此时如何桥接到slf4j进行统一管理?方法如下:
-
排除掉第三方框架的日志实现,第三框框架(log4j-demo)使用的log4j,要先排除掉。
<dependency> <groupId>com.warybee</groupId> <artifactId>log4j-demo</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion> </exclusions> </dependency>
-
引入桥接器
<!-- 引入log4j桥接器 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>1.7.32</version> </dependency>