Log4j2 — LogEvent的传递及配置文件重定位
前言
Log4j2的介绍可以参考上一篇博客。
Log4j2很好的一点是可以用configuration file来配置log system。但是这个配置文件的存放位置比较纠结一些。文中会介绍如何更改Log4j2配置文件的路径和名称。
目录
本文的内容将回答如下问题:
1、如何产生LogEvent?
2、LogEvent的传递是怎样的?
3、如何更改Log4j2配置文件的的名称和路径?
正文
1、如何产生LogEvent?
在调用Logger对象的info、error、trace等函数时,就会产生LogEvent。LogEvent跟LoggerConfig一样,也是由Level的。LogEvent的Level主要是用在Event传递时,判断在哪里停下。具体的可以参考上一篇日志。
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class Test { private static Logger logger = LogManager.getLogger("HelloWorld"); public static void main(String[] args){ Test.logger.info("hello,world"); Test.logger.error("There is a error here"); } }
如代码中所示,这样就产生了两个LogEvent。
2、LogEvent的传递是怎样的?
我们在IDE中运行一下这个程序,看看会有什么输出。
发现,只有ERROR的语句输出了,那么INFO的语句呢?
不着急,先来看看工程目录结构:
可以看到,工程中没有写入任何的配置文件。所以,application应该是使用了默认的LoggerConfig Level。那么默认的Level是多少呢?
在log4j2的源文件中,可以看到其DefaultConfiguration类的java doc,描述如下:
/**
* 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.
可见,默认的输出地是console,默认的级别是ERROR级别。
那么,为什么默认ERROR级别会导致INFO级别的信息被拦截呢?
看如下表格:
左边竖栏是Event的Level,右边横栏是LoggerConfig的Level。Yes的意思就是这个event可以通过filter,no的意思就是不能通过filter。
可以看到,INFO级别的Event是无法被ERROR级别的LoggerConfig的filter接受的。所以,INFO信息不会被输出。
3、如何改变Log4j2的名称和路径?
如果想要改变默认的配置,那么就需要configuration file。Log4j的配置是写在log4j.properties文件里面,但是Log4j2就可以写在XML和JSON文件里了。
(1)放在classpath(src)下,以log4j2.xml命名
使用Log4j2的一般都约定俗成的写一个log4j2.xml放在src目录下使用。这一点没有争议。
(2)将配置文件放到别处
在系统工程里面,将log4j2的配置文件放到src目录底下很不方便。如果能把工程中用到的所有配置文件都放在一个文件夹里面,当然就更整齐更好管理了。但是想要实现这一点,前提就是Log4j2的配置文件能重新定位到别处去,而不是放在classpath底下。
那么,有这个可能吗?
看看文档里怎么说吧:
1.Log4j will inspect the "log4j.configurationFile" system property and, if set,will attempt to load the configuration using the ConfigurationFactory that matches the file extension.
2.If no system property is set the JSON ConfigurationFactory will look for log4j2-test.json or log4j2-test.jsn in the classpath.
3.If no such file is found the XML ConfigurationFactory will look for log4j2-test.xml in the classpath.
4.If a test file cannot be located the JSON ConfigurationFactory will look for log4j2.json or log4j2.jsn on the classpath.
5.If a JSON file cannot be located the XML ConfigurationFactory will try to locate log4j2.xml on the classpath.
6.If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.
可见,如果没有设置"log4j.configurationFile" system property的话,application将在classpath中按照如下查找顺序来找配置文件:
log4j2-test.json 或log4j2-test.jsn文件
log4j2-test.xml文件
log4j2.json 或log4j2.jsn文件
log4j2.xml文件
这就是为什么在src目录底下放log4j2.xml文件可以被识别的原因了。
如果想将配置文件重命名并放到别处,就需要设置系统属性log4j.configurationFile。
设置的方式是在VM arguments中写入该属性的key和value:
-Dlog4j.configurationFile="D:\learning\blog\20130115\config\LogConfig.xml"
在myeclipse中,就是 右键-》run as -》run configuration-》右边窗口的“(x)=argument”=》VM arguments
然后写入上述key和value即可。
-D是参数,不能缺少。
测试
在“D:\learning\blog\20130115\config\”路径下编写文件:
root LoggerConfig的Level设为INFO。
在myeclipse中写入log4j.configurationFile系统属性:
测试的java程序如上文,在此不再重复。运行,console输出如下:
期待已久的INFO语句出现了。
总结:
这次测试最纠结的地方是在配置文件的重定位上。先google了一番,在overflowstack上看到有人有一样的问题,CSDN上也是,不过都没人说怎么解决。翻看手册,是看到了log4j.configurationFile这个设置系统属性的地方。试了一下(当时没写参数-D),没有成功,以为这个方法不对。就在Log4j2的网站上下载了源代码,一点点查找改路径的地方。找到最后,还是从log4j.configurationFile这个系统属性上入手。无奈,又回到原点。最后竟然是没写参数-D。哎,苍天呐……