以编程方式初始化log4j2(TWO)的更好方法

时间:2014-12-16 14:56:03

标签: java logging configuration log4j2

这就是我正在做的加载log4j2.xml文件,从另一个属性文件指定日志文件位置以保持配置简单以便支持:

MyProperties props = MyProperties.getInstance();
System.setProperty(MyConstants.AUDIT_LOG_ENV_VAR,
        props.getAuditLogFileName());
ConfigurationSource source =
        new ConfigurationSource(new FileInputStream(new File(
                System.getProperty(MyConstants.PROPERTIES_FILE_ENV_VAR)
                    + "/log4j2.xml")));
Configurator.initialize(null, source);

和log4j2将选择并使用我的文件名,因为我已使用envvar替换在Appender中指定它:

<File name="AuditLogger" fileName="${sys:AUDIT_LOG}">
  <PatternLayout pattern="DATETIME  %d{yyyy-MM-dd HH:mm:ss:SSS zzz}%n%msg%n" />
</File>

但是我不喜欢它,因为在将下一行代码重新读回文件名值之前,有一种将文件名值推送到系统环境的气味。

我喜欢Configure log4j2 programmatically using ConfigurationFactory,但似乎没有类似的方法在log4j2.xml文件之上构建更多内容 - 或者是否存在?

1 个答案:

答案 0 :(得分:2)

通常,log4j2团队不建议使用程序化配置:api和核心jar之间的分离是为了让开发人员明确区分API和实现。程序化配置依赖于实现细节,因此可能会在将来的版本中中断。

如果配置无法完成,请告知我们,以便我们改进。

对于您的特定用例:看起来您希望在 log4j2根据该值初始化自身之前将系统属性设置为某个值。如果这是一个独立的应用程序,避免依赖log4j2实现细节的一种方法是在引用任何log4j2类之前设置所有必要的系统属性:

public class MainWrapper {
    public static void main(String[] args) {
        System.setProperty("key", "value");
        // ... 
        ActualMain.main(args); // delegate to the actual start of the application
    }
}

另一种我想引起你注意的是创建自己的自定义查找。这可以使用log4j2 plugin在几行代码中完成。这也依赖于一些实现细节,但结果更强大且可重用。

package com.mycompany;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.AbstractLookup;
import org.apache.logging.log4j.core.lookup.StrLookup;

/** Looks up keys in MyProperties singleton. */
@Plugin(name = "MyProperties", category = StrLookup.CATEGORY)
public class MyPropertiesLookup extends AbstractLookup {
    @Override public String lookup(final LogEvent event, final String key) {
        return MyProperties.getInstance().getValue(key);
    }
}

然后,在您的配置中,您可以使用自定义查找而不是系统属性:

<File name="AuditLogger" fileName="${MyProperties:AUDIT_LOG}">
  <PatternLayout pattern="DATETIME  %d{yyyy-MM-dd HH:mm:ss:SSS zzz}%n%msg%n" />
</File>