java日志系统log4j配置解析过程,源码分析

编程

log4j 可以看成是非常类似jdk logger 结构 ,有个logger 与logManger
都是在logManger的静态块中初始化类,加载配置文件

Logger.getLogger(Test.class);
1
从getLogger开始,就启动了log4j的整个工作流程,通过调用LogManager获取logger实例

return LogManager.getLogger(clazz.getName());
1
LogManager类里面有个静态块static{},【初始化尝试读取配置文件】先尝试加载log4j.xml [DEFAULT_XML_CONFIGURATION_FILE] ,再尝试log4j.properties [DEFAULT_CONFIGURATION_FILE]

url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
if(url == null) {
    url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
}
1
2
3
4
如果找到了配置文件,就会开始解析配置文件

//url是配置文件路径,LogManager.getLoggerRepository()是Hierarchy类
OptionConverter.selectAndConfigure(url, configuratorClassName,
                       LogManager.getLoggerRepository());
//继而开始调用
configurator = new PropertyConfigurator();
//加载properties配置文件
configurator.doConfigure(url, hierarchy);
//从这开始就解析所有配置信息的入口,可以设置断点,debug调试
doConfigure(props, hierarchy);
1
2
3
4
5
6
7
8
9
在doConfigure(props, hierarchy)方法里可以看到
1、添加java vm 启动参数 -Dlog4j.configDebug=true或-Dlog4j.debug=true可以打开Loglog的debug输出 (Loglog是log4j内部的输出调试类)

//配置文件中打开Loglog的输出,debug
    String value = properties.getProperty(LogLog.DEBUG_KEY);
    if(value == null) {
      value = properties.getProperty("log4j.configDebug");
      if(value != null)
    LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
    }

    if(value != null) {
      LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
    }
1
2
3
4
5
6
7
8
9
10
11
2、一些配置,log4j.reset、log4j.threshold

    String reset = properties.getProperty(RESET_KEY);
    if (reset != null && OptionConverter.toBoolean(reset, false)) {
          hierarchy.resetConfiguration();
    }

    String thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PREFIX,
                               properties);
    if(thresholdStr != null) {
      hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr,
                             (Level) Level.ALL));
      LogLog.debug("Hierarchy threshold set to ["+hierarchy.getThreshold()+"].");
    }
1
2
3
4
5
6
7
8
9
10
11
12
3、配置root logger,LoggerFactory等等

configureRootCategory(properties, hierarchy);
configureLoggerFactory(properties);
1
2
PropertyConfigurator类是主要的配置解析类,OptionConverter类是转换值true到boolen,获取根据key从properties取值交给PropertyConfigurator解析。

LogManager的静态块主要是初始化自己(实例化repositorySelector,读取配置),【root logger默认debug】【Hierarchy 是loggerfactory,提供有层级的,父子关系的logger】

Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
1
LogManager.getLogger里面getLoggerRepository().getLogger(name);
就是通过Hierarchy.getLogger(name)取得logger实例
Hierarchy内部使用Hashtable ht 保存key为name的logger实例,单例模式,
1
2
3
这样就完成了获取logger

当调用logger记录日志时,默认是debug等级
logger.debug(“debug”);

logger.debug("debug");
触发
forcedLog(FQCN, Level.DEBUG, message, null);
callAppenders(new LoggingEvent(fqcn, this, level, message, t));

//writes 初始0,  writes += c.aai.appendLoopOnAppenders(event);就是配置的appender(aai是AppenderAttachableImpl就是logger里保存定义的多个appender)
if(writes == 0) {
      repository.emitNoAppenderWarning(this);//输出没有配置appender的警告
    }
1
2
3
4
5
6
7
8
9
如果logger没有找到appender,就是具体的日志处理,就报错了,不执行,所以【log4j必须先配置再使用】

可以在main方法中 【BasicConfigurator.configure();】 快速初始化

log4j:WARN No appenders could be found for logger (Test).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
1
2
3
【一些主要方法的功能】
org.apache.log4j.PropertyConfigurator#configureRootCategory
解析配置文件中对root logger的配置 (log4j.rootLogger开头的配置)

org.apache.log4j.PropertyConfigurator#parseAdditivityForLogger
处理非root logger的additivity属性(默认为真,继承父logger的appenders)

org.apache.log4j.PropertyConfigurator#parseAppender
实例化配置中的appender(log4j.appender.开头 + appenderName)

org.apache.log4j.PropertyConfigurator#parseCategory
配置包括root logger的各个包内的logger (logger是Category的子类,表示各个不同包内的logger)
————————————————
 

以上是 java日志系统log4j配置解析过程,源码分析 的全部内容, 来源链接: utcz.com/z/512547.html

回到顶部