log4j 2是log4j的升级版
log4j 2简介:http://logging.apache.org/log4j/2.x/manual/index.html
1. 下载log4j 2
log4j 2官网:http://logging.apache.org/log4j/2.x/
log4j 2下载页面:http://logging.apache.org/log4j/2.x/download.html
我下载的是”apache-log4j-2.0-beta9-bin.zip”,解压该文件,将log4j-api-2.0-beta9.jar、log4j-core-2.0-beta9.jar导入项目,即可使用log4j 2
2. 初识log4j 2
package log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class Test01 {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(Test01.class.getName());
logger.trace("trace");
logger.debug("debug");
logger.info("hello");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
}
}
Output:
12:24:25.398 [main] ERROR log4j2.Test01 - error
12:24:25.401 [main] FATAL log4j2.Test01 - fatal
代码中写了6种输出,为什么只出来”error”,”fatal”呢?
原来log4j 2初始化时,自动从src目录加载配置文件。配置文件的格式有两种:json和xml
配置文件的优先级(从高到低):
log4j2-test.json(或log4j2-test.jsn)
log4j2-test.xml
log4j2.json(或log4j2.jsn)
log4j2.xml
默认配置文件
log4j 2初始化时,优先从src目录下找”log4j2-test.json(或log4j2-test.jsn)”,如果没找到,会继续找”log4j2-test.xml”,以此类推
刚才的例子中,src目录下没有配置文件,因此log4j 2将使用默认配置文件
默认配置文件由DefaultConfiguration类提供。DefaultConfiguration内容:
* Licensed to the Apache Software Foundation (ASF) under one or more
package org.apache.logging.log4j.core.config;
import java.io.Serializable;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.apache.logging.log4j.util.PropertiesUtil;
/**
* The default configuration writes all output to the Console using the default logging level. You configure default
* logging level by setting the system property "org.apache.logging.log4j.level" to a level name. If you do not
* specify the property, Log4j uses the ERROR Level. Log Events will be printed using the basic formatting provided
* by each Message.
*/
public class DefaultConfiguration extends BaseConfiguration {
/**
* The name of the default configuration.
*/
public static final String DEFAULT_NAME = "Default";
/**
* The System Property used to specify the logging level.
*/
public static final String DEFAULT_LEVEL = "org.apache.logging.log4j.level";
/**
* Constructor to create the default configuration.
*/
public DefaultConfiguration() {
setName(DEFAULT_NAME);
final Layout<? extends Serializable> layout =
PatternLayout.createLayout("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n", null, null, null, null);
final Appender appender =
ConsoleAppender.createAppender(layout, null, "SYSTEM_OUT", "Console", "false", "true");
appender.start();
addAppender(appender);
final LoggerConfig root = getRootLogger();
root.addAppender(appender, null, null);
final String levelName = PropertiesUtil.getProperties().getStringProperty(DEFAULT_LEVEL);
final Level level = levelName != null && Level.valueOf(levelName) != null ?
Level.valueOf(levelName) : Level.ERROR;
root.setLevel(level);
}
@Override
protected void doConfigure() {
}
}
DefaultConfiguration提供的默认配置等同于如下配置:
<?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>
log4j 2定义了8个事件级别:ALL,TRACE, DEBUG, INFO, WARN, ERROR ,FATAL,OFF(由低到高)
由于Root level设置为”error”,因此只有等于或高于”error”级别的事件才能输出。所以刚才的例子中只输出了”error”,”fatal”
3. log4j 2读取配置文件
log4j 2读取的配置文件可以分为三类:src下的配置文件、绝对路径的配置文件、相对路径的配置文件
3.1 log4j 2读取src下的配置文件
在src目录下创建log4j2.xml,复制log4j 2默认配置的内容到log4j2.xml,并将log4j2.xml里的Root level改为”trace”,内容如下:
<?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="trace">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
再次运行Test01 ,输出如下:
13:24:03.939 [main] TRACE log4j2.Test01 - trace
13:24:03.942 [main] DEBUG log4j2.Test01 - debug
13:24:03.942 [main] INFO log4j2.Test01 - info
13:24:03.942 [main] WARN log4j2.Test01 - warn
13:24:03.942 [main] ERROR log4j2.Test01 - error
13:24:03.942 [main] FATAL log4j2.Test01 - fatal
3.2 log4j 2读取绝对路径的配置文件
将log4j2.xml拷贝到E盘下,并将其改名为Test02.xml,然后将Test02.xml里的Root level设置为”debug”
测试代码如下
package log4j2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource;
import org.apache.logging.log4j.core.config.Configurator;
public class Test02 {
public static void main(String[] args) throws FileNotFoundException {
//绝对路径配置文件
ConfigurationSource source = new ConfigurationSource();
source.setLocation("E:\\Test02.xml");
source.setFile(new File("E:\\Test02.xml"));
source.setInputStream(new FileInputStream("E:\\Test02.xml"));
Configurator.initialize(null, source);
Logger logger = LogManager.getLogger(Test02.class.getName());
logger.trace("trace");
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
}
}
Output:
14:54:46.102 [main] DEBUG log4j2.Test02 - debug
14:54:46.105 [main] INFO log4j2.Test02 - info
14:54:46.105 [main] WARN log4j2.Test02 - warn
14:54:46.105 [main] ERROR log4j2.Test02 - error
14:54:46.105 [main] FATAL log4j2.Test02 - fatal
可以看到trace内容并没有输出,说明读取配置文件成功
3.3 log4j 2读取相对路径的配置文件
获取运行时路径的方法
package log4j2;
public class Test03 {
public static void main(String[] args) {
System.out.println("Working Directory = " +
System.getProperty("user.dir"));
}
}
Output:
Working Directory = E:\project\eclipse\Test
在”E:\project\eclipse\Test\bin\log4j2”新建Test03文件夹。
然后将log4j2.xml拷贝到”E:\project\eclipse\Test\bin\log4j2\Test03”下,并将其改名为Test03.xml,然后将Test03.xml里的Root level设置为”info”
测试代码如下:
package log4j2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
public class Test03 {
public static void main(String[] args) {
System.out.println("Working Directory = " +
System.getProperty("user.dir"));
//相对路径配置文件
System.setProperty(XMLConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "log4j2/Test03/Test03.xml");
Logger logger = LogManager.getLogger(Test03.class.getName());
logger.trace("trace");
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
}
}
Output:
Working Directory = E:\project\eclipse\Test
15:11:09.870 [main] INFO log4j2.Test01 - info
15:11:09.872 [main] WARN log4j2.Test01 - warn
15:11:09.873 [main] ERROR log4j2.Test01 - error
15:11:09.873 [main] FATAL log4j2.Test01 - fatal
可以看到trace,debug内容并没有输出,说明读取配置文件成功
下面的测试均采用log4j 2读取src下配置文件的方式
4. Appenders
Appender负责定义日志输出的目的地,它可以是控制台(ConsoleAppender)、文件(FileAppender)、以Email的形式发送出去(SMTPAppender)等
Log4j 2官网介绍了20种Appender:http://logging.apache.org/log4j/2.x/manual/appenders.html
下面介绍3种常用的Appender:ConsoleAppender、FileAppender、RollingFileAppender
4.1 ConsoleAppender
ConsoleAppender将输出写到System.err或System.out。上面测试例子中的Appender均为ConsoleAppender,输出写到了System.out。如果想将输出写到System.err,设置Console标签下的target为"SYSTEM_ERR "即可
4.2 FileAppender
FileAppender将输出写到指定文件,在File标签下设置fileName即可。fileName可以是绝对路径的文件也可以是相对路径的文件
写到绝对路径文件
修改src下的log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<!--FileAppender-->
<File name="File" fileName="E:\Test01.log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
运行Test01,log将写到E:\Test01.log
写到相对路径文件
修改src下的log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<!--FileAppender-->
<File name="File" fileName="logs/Test01.log">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</File>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="File"/>
</Root>
</Loggers>
</Configuration>
运行Test01,log将写到E:\project\eclipse\Test\logs\Test01.log
4.3 RollingFileAppender
RollingFileAppender跟FileAppender的基本用法一样。但RollingFileAppender可以设置log文件的size(单位:KB/MB/GB)上限、数量上限,当log文件超过设置的size上限,会自动被压缩。RollingFileAppender可以理解为滚动输出日志,如果log4j 2记录的日志达到上限,旧的日志将被删除,腾出的空间用于记录新的日志
修改src下的log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<!--RollingFile-->
<RollingFile name="RollingFile" fileName="logs/Test.log"
filePattern="logs/$${date:yyyy-MM}/Test-%d{MM-dd-yyyy}-%i.log.gz">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="1 KB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
该配置设置日志写到Test.Log,如果Test.log的大小超过1KB,log4j 2会将Test.log制成压缩文件(压缩文件的命名格式是由filePattern设置的)。DefaultRolloverStrategy 标签的max设置压缩文件的上限(默认值为7)
将Test01的输出循环50次
package log4j2;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource;
import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
public class Test01 {
public static void main(String[] args) throws FileNotFoundException {
Logger logger = LogManager.getLogger(Test01.class.getName());
for (int i = 0; i < 50; i++) {
logger.trace("trace");
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
}
}
}
运行Test01可以在E:\project\eclipse\Test\logs\2014-02看到如下压缩文件
5. Filters
Filter可以过滤log事件,并控制log输出
log4j 2定义了10种 Filter:http://logging.apache.org/log4j/2.x/manual/filters.html
下面介绍一下BurstFilter的用法
BurstFilter可以控制某一级别的log的并发情况
修改src下的log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Appenders>
<RollingFile name="RollingFile" fileName="logs/app.log"
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz">
<BurstFilter level="INFO" rate="16" maxBurst="100"/>
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy />
<SizeBasedTriggeringPolicy size="1 KB"/>
</Policies>
<DefaultRolloverStrategy max="10"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
<BurstFilter level="INFO" rate="16" maxBurst="100"/>标签解释
level:BurstFilter过滤的事件级别
rate:每秒允许的log事件的平均值
maxBurst:当BurstFilter过滤的事件超过rate值,排队的log事件上限。超过此上限的log,将被丢弃。默认情况下maxBurst = 10*rate
按以上配置,假定每个log事件的执行时间较长,输出117个log事件(INFO级别)到RollingFileAppenders,BurstFilter会过滤得到INFO级别的log事件,之后会发生:16个log事件在执行,100个等待执行,1个被丢弃。
6. log4j 2指定某个类的log输出级别
在log4j2.xml设置Test01的输出级别
修改src下的log4j2.xml
<?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>
<Logger name="log4j2.Test01" level="trace">
<AppenderRef ref="Console"/>
</Logger>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
修改Test01
package log4j2;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory.ConfigurationSource;
import org.apache.logging.log4j.core.config.XMLConfigurationFactory;
public class Test01 {
public static void main(String[] args) throws FileNotFoundException {
Logger logger = LogManager.getLogger(Test01.class.getName());
logger.trace("trace");
logger.debug("debug");
logger.info("info");
logger.warn("warn");
logger.error("error");
logger.fatal("fatal");
}
}
运行Test01
Output:
16:12:08.662 [main] TRACE log4j2.Test01 - trace
16:12:08.662 [main] TRACE log4j2.Test01 - trace
16:12:08.665 [main] DEBUG log4j2.Test01 - debug
16:12:08.665 [main] DEBUG log4j2.Test01 - debug
16:12:08.665 [main] INFO log4j2.Test01 - info
16:12:08.665 [main] INFO log4j2.Test01 - info
16:12:08.665 [main] WARN log4j2.Test01 - warn
16:12:08.665 [main] WARN log4j2.Test01 - warn
16:12:08.666 [main] ERROR log4j2.Test01 - error
16:12:08.666 [main] ERROR log4j2.Test01 - error
16:12:08.666 [main] FATAL log4j2.Test01 - fatal
16:12:08.666 [main] FATAL log4j2.Test01 - fatal
可以看到Test01里的日志输出了两次
原来log4j 2的配置文件都有一个root logger,root logger的level为”error”,appender为”console”。如果配置文件中没有设置Test01 logger,那么Test01将使用root logger;如果配置文件中设置了Test01 logger,则Test01 logger(子logger)的appender先输出,但Test01 logger的事件还会传到root logger(父logger)的appender,然后再次输出。
为了避免重复输出,可以在Logger 标签下设置additivity为"false",禁止子logger在父logger的appender里输出。修改后的log4j2.xml:
<?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>
<Logger name="log4j2.Test01" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Output:
16:30:52.339 [main] TRACE log4j2.Test01 - trace
16:30:52.342 [main] DEBUG log4j2.Test01 - debug
16:30:52.342 [main] INFO log4j2.Test01 - info
16:30:52.342 [main] WARN log4j2.Test01 - warn
16:30:52.342 [main] ERROR log4j2.Test01 - error
16:30:52.342 [main] FATAL log4j2.Test01 - fatal
7. log4j 2可以定时检测配置文件的变化
通过设置monitorInterval属性,即可设置log4j 2自动检测配置文件的时间间隔(单位:秒),最小间隔为5秒。log4j 2检测到配置文件有变化,会重新配置自己。
<?xml version="1.0" encoding="UTF-8"?>
<Configuration monitorInterval="30">
</Configuration>
8. Status
文中的配置文件的开头都有如下设置
<Configuration status="WARN">
status究竟有什么用处呢?
log4j 2定义的status级别有8个:ALL,TRACE, DEBUG, INFO, WARN, ERROR ,FATAL,OFF
其实status属性是帮助开发者找错用的,它可以检测log4j 2的配置文件是否有错,也可以检测到死循环的logger
9.Layouts
Appenders标签内的PatternLayout标签控制log事件的输出格式
log4j 2官网的Layouts介绍:http://logging.apache.org/log4j/2.x/manual/layouts.html