| 目录 [+] |
这里有一篇讲Log4j配置的文章,描述很简洁:配置Log4j - Author: zJun - www.blogjava.net。同样的内容尽量不再介绍。
也可以看看Java Logging使用经验。
下面提及的Log4j都是指1.2版本,源码是apache-log4j-1.2.16-src。
1 LoggerRepository, logger, appender, layout
Log4j has three main components: loggers, appenders and layouts. These three types of components work together to enable developers to log messages according to message type and level, and to control at runtime how these messages are formatted and where they are reported.--引用自http://logging.apache.org/log4j/1.2/manual.html
一个配置文件可以有多个logger,logger可以继承,rootLogger必须存在。每个logger可以有多个Appender,真正记录日志的是Appender,即一条日志可以输出到多个目标位置,Appender有多种预置实现,通常都可以配置属性。每个Appender有一个layout,layout有多种预置实现,通常都可以配置属性。
这些关系都保存在LoggerRepository,默认使用的是Hierarchy这个实现类,这是在LogManager写死的。
static {
Hierarchy h = new Hierarchy(new org.apache.log4j.spi.RootLogger((Level) Level.DEBUG));
repositorySelector = new DefaultRepositorySelector(h);
...
// 加载配置文件,搜索顺序是system property "log4j.configuration"代表的文件 -> "log4j.xml" -> "log4j.properties";
// 之后通过PropertyConfigurator/DOMConfigurator类进行配置。
OptionConverter.selectAndConfigure(url, configuratorClassName, LogManager.getLoggerRepository());
}
2 解析及配置原理
)PropertyConfigurator/DOMConfigurator类有一些parse/configure方法。对某一部分parse完成之后,Appender通过org.apache.log4j.Category.addAppender(Appender newAppender)设置,layout通过org.apache.log4j.Appender.setLayout(Layout layout)设置。)Appender/layout的属性通过org.apache.log4j.config.PropertySetter.setProperty方法设置,用到了java.beans.Introspector.decapitalize, java.beans.PropertyDescriptor.getWriteMethod之类的方法,这些方法是通过反射来完成工作的。调用的都是set方法,所有set方法对应的属性都可以配置。比如FileAppender.bufferedIO、PatternLayout.conversionPattern,bufferedIO、conversionPattern就是属性名,第一个字符不区分大小写。
3 配置
3.1 基本配置
"log4j.rootLogger" / "log4j.rootCategory" = levelName + ',' + appender1 + ',' + ... + appenderN这是配置root logger。
"log4j.logger" + loggerName = levelName + ',' + appender1 + ',' + ... + appenderN
这是配置普通logger,有特殊需要的时候配置,不配置就继承自rootLogger;
还可以通过loggerName体现继承关系,就像Java的package;
一般都是用clazz.getName()作为loggerName,在给依赖的库做单独配置的时候就需要用到。
"log4j.appender." + appenderName + ".layout" = layoutClassName
这是设置layout。还可以继续设置layout的属性。
3.2 变量替换
所有的选项都允许变量替换。使用方式:${system_property}。比如,${java.home}会被替换为Java安装目录。可以利用这个功能给日志文件设置一个自定义的保存路径,给java增加启动选项-Dmyapp.path={absolute_path},修改配置文件:log4j.appender.R.File=${myapp.path}/logs/myapp.log
3.3 把日志发送到指定邮箱
严重错误最好发送邮件通知,可以通过org.apache.log4j.net.SMTPAppender来做,这个类需要JavaMail API,另外,Since 1.2.16, SMTP over SSL is supported by setting SMTPProtocol to "smtps"。3.4 关闭日志、强制输出缓存
org.apache.log4j.LogManager.shutdown()方法可以关闭日志,同时强制输出缓存的日志并且清除所有的appenders。如果发现什么问题,可以看看http://logging.apache.org/log4j/1.2/faq.html#unload
3.5 在运行状态改变日志配置
测试代码见附录:测试代码。)配置
把配置文件放在自定义的目录,比如${myapp.path}/conf/log4j-reloadable.properties,禁用自动加载,自行加载,通过PropertyConfigurator/DOMConfigurator.configure自行配置。
在管理员控制台提供整个配置文件的内容,允许任意修改。修改完之后点击提交。
代码里面先调用LogManager.shutdown();,再调用PropertyConfigurator/DOMConfigurator.configure。
配置成功的话,把新的配置写到配置文件里边(注意原子性以及失败恢复);失败的话,不做任何操作,回到编辑页面,给出错误提醒。
)注意
不能直接通过PropertyConfigurator/DOMConfigurator.configure在运行状态改变配置,否则会有问题。因为configure方法是直接new了一个新的实例并配置,所以每调用一次configure方法就会增加每条日志的输出次数。configureAndWatch方法也会有类似的问题,因为相应的XyzWatchdog.doOnChange()也是这样处理的。
可以看相应源码或者http://logging.apache.org/log4j/1.2/faq.html#duplicate-messages。
3.6 定制log4j
)自定义LoggerFactory,通过makeNewLoggerInstance方法返回自定义的Logger类;- log4j.loggerFactory = loggerFactoryClassName。这是设置自定义的loggerFactory,如果有自定义的属性,那通过"log4j.factory." + loggerFactoryClassPropertyName = value设置。
- 经测试,这个配置不好用,用LogManager.getLogger(String name, LoggerFactory factory)包装一个Logger.getLogger(String name)是没问题的。
)自定义Appender,比如写到MongoDB。
)自定义layout,比如输出为XML格式。
3.7 其他配置
)log4j.debug=true,会额外输出一些log4j本身的调试信息到console,便于对照代码。)"log4j.additivity." + loggerName = true/false,通过org.apache.log4j.Category.setAdditivity(boolean additive)设置,不设置就是null。
3.8 深入阅读
* Short introduction to log4j - Author: Ceki Gülcü - logging.apache.org* http://logging.apache.org/log4j/1.2/faq.html
* http://logging.apache.org/log4j/1.2/apidocs/
* http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
4 附录:测试代码
4.1 ReloadTest.java
Pre[-]
package logging;
import org.apache.log4j.*;
import org.apache.log4j.spi.*;
public class ReloadTest {
private static final Logger LOG = Logger.getLogger(ReloadTest.class.getName());
public static void main(String[] args) {
PropertyConfigurator.configure(ReloadTest.class.getResource("reloadtest.properties"));
final LoggerRepository repository = LogManager.getLoggerRepository();
LOG.info(repository);
final Logger root = LogManager.getRootLogger();
{
LOG.info(loggerToString(root));
LOG.trace("trace1 before set level");
root.setLevel(Level.TRACE);
LOG.trace("trace2 after set level");
root.setLevel(Level.DEBUG);
}
printLoggers();
{
// repository.resetConfiguration();
// repository.shutdown();
LogManager.shutdown();
LOG.info("info1 after LogManager.shutdown");
PropertyConfigurator.configure(ReloadTest.class.getResource("reloadtest.properties"));
LOG.info("info2 after PropertyConfigurator.configure");
}
printLoggers();
LOG.info("last info");
}
private static void printLoggers() {
LOG.info("printLoggers============");
java.util.Enumeration iter = LogManager.getCurrentLoggers();
Logger log;
while (iter.hasMoreElements()) {
log = (Logger) iter.nextElement();
LOG.info(loggerToString(log));
}
}
private static String loggerToString(Logger log) {
return String.format("{log: name=%s, level=%s, className=%s}", log.getName(), log.getLevel(), log.getClass().getName());
}
}
4.2 reloadtest.properties
放到ReloadTest.java所在的目录,内容来自http://logging.apache.org/log4j/1.2/manual.html,略有改动。log4j.rootLogger=DEBUG, A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout # Print the date in ISO 8601 format log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n # Print only messages of level WARN or above in the package com.foo. log4j.logger.com.foo=WARN log4j.logger.com.foo.bar=DEBUG #log4j.debug=true
5 附录:Log4j所有可用的appender/layout属性
Log4j manual没有列出所有的可配置属性,没有完整的例子。Log4j的作者写了一本书,是完整的教程。下面的属性是通过 /tool-java/blob/master/src/Log4jPropertiesDumper.java 生成的。
5.1 属性简介
)有些属性是不需要设置的,比如writer。PropertySetter.convertArg(String val, Class type)方法会把字符串转换为别的数据类型,但是类型很有限,所以很多属性都是转换不出来的类型,以至于无法设置。当然,有些数据不需要在convertArg方法里转换,比如RollingFileAppender的maxFileSize属性,set方法接受的是字符串,在set方法里边转换可能出现的KB-MB-GB。)有些属性是相同的含义,不需要都设置,比如immediateFlush跟bufferedIO在FileAppender是一个意思,只需要设置其中一个。
)这个列表只是方便简易浏览,每个属性允许的值没有列出来,比如ConsoleAppender的target属性只能接受"System.out"跟"System.err",这些得参考JavaDoc或者源码。
)挑几个比较公用的说一下:
Appender接口
errorHandler
layout
name
AppenderSkeleton抽象类
threshold 就是Level
WriterAppender 不是抽象类,主要用于继承
encoding 字符集
immediateFlush 立即强制输出
writer 没用,我是设置不了
FileAppender
append
bufferedIO
bufferSize
file
5.2 可用的appender属性
Pre[-]
org.apache.log4j.AsyncAppender
blocking
bufferSize
errorHandler
layout
locationInfo
name
threshold
org.apache.log4j.ConsoleAppender
encoding
errorHandler
follow
immediateFlush
layout
name
target
threshold
writer
org.apache.log4j.DailyRollingFileAppender
append
bufferSize
bufferedIO
datePattern
encoding
errorHandler
file
immediateFlush
layout
name
threshold
writer
org.apache.log4j.FileAppender
append
bufferSize
bufferedIO
encoding
errorHandler
file
immediateFlush
layout
name
threshold
writer
org.apache.log4j.RollingFileAppender
append
bufferSize
bufferedIO
encoding
errorHandler
file
immediateFlush
layout
maxBackupIndex
maxFileSize
maximumFileSize
name
threshold
writer
org.apache.log4j.WriterAppender
encoding
errorHandler
immediateFlush
layout
name
threshold
writer
org.apache.log4j.jdbc.JDBCAppender
URL
bufferSize
driver
errorHandler
layout
locationInfo
name
password
sql
threshold
user
org.apache.log4j.lf5.LF5Appender
callSystemExitOnClose
errorHandler
layout
maxNumberOfRecords
name
threshold
org.apache.log4j.net.JMSAppender
URLPkgPrefixes
errorHandler
initialContextFactoryName
layout
locationInfo
name
password
providerURL
securityCredentials
securityPrincipalName
threshold
topicBindingName
topicConnectionFactoryBindingName
userName
org.apache.log4j.net.SMTPAppender
SMTPDebug
SMTPHost
SMTPPassword
SMTPPort
SMTPProtocol
SMTPUsername
bcc
bufferSize
cc
errorHandler
evaluator
evaluatorClass
from
layout
locationInfo
name
replyTo
sendOnClose
subject
threshold
to
org.apache.log4j.net.SocketAppender
advertiseViaMulticastDNS
application
errorHandler
layout
locationInfo
name
port
reconnectionDelay
remoteHost
threshold
org.apache.log4j.net.SocketHubAppender
advertiseViaMulticastDNS
application
bufferSize
errorHandler
layout
locationInfo
name
port
threshold
org.apache.log4j.net.SyslogAppender
errorHandler
facility
facilityPrinting
header
layout
name
syslogHost
threshold
org.apache.log4j.net.TelnetAppender
errorHandler
layout
name
port
threshold
org.apache.log4j.nt.NTEventLogAppender
errorHandler
layout
name
source
threshold
org.apache.log4j.varia.ExternallyRolledFileAppender
append
bufferSize
bufferedIO
encoding
errorHandler
file
immediateFlush
layout
maxBackupIndex
maxFileSize
maximumFileSize
name
port
threshold
writer
org.apache.log4j.varia.NullAppender
errorHandler
layout
name
threshold
5.3 可用的layout属性
Pre[-]
org.apache.log4j.EnhancedPatternLayout
conversionPattern
org.apache.log4j.HTMLLayout
locationInfo
title
org.apache.log4j.PatternLayout
conversionPattern
org.apache.log4j.SimpleLayout
org.apache.log4j.TTCCLayout
categoryPrefixing
contextPrinting
dateFormat
threadPrinting
timeZone
org.apache.log4j.xml.XMLLayout
locationInfo
properties
=文章版本=
2013040x20130501 修改一下格式,顺便增减一部分内容
20130506 改为html格式
No comments:
Post a Comment