自定义ConfigurationFactory与log4j2

时间:2017-05-28 13:19:23

标签: java debugging logging log4j2

我试图Initialize Log4j by Combining Configuration File with Programmatic Configuration

我遵循了手册(虽然它的语法不是很正确,而且已经过时了),这导致了以下类:

CustomConfigurationFactory.java:

package factory;

import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.plugins.Plugin;

import java.net.URI;

@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
@Order(1)
public class CustomConfigurationFactory extends ConfigurationFactory {

    /**
     * Valid file extensions for XML files.
     */
    private static final String[] SUFFIXES = new String[]{".xml", "*"};

    /**
     * Return the Configuration.
     *
     * @param source The InputSource.
     * @return The Configuration.
     */
    public Configuration getConfiguration(LoggerContext context, ConfigurationSource source) {

        return new CustomConfiguration(context, source);

    }

    /**
     * Returns the file suffixes for XML files.
     * @return An array of File extensions.
     */
    public String[] getSupportedTypes() {

        return SUFFIXES;

    }

}

CustomConfiguration.java:

package factory;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.xml.XmlConfiguration;

import java.util.Map;

public class CustomConfiguration extends XmlConfiguration {

    CustomConfiguration(LoggerContext context, ConfigurationSource configSource) {

        super(context, configSource);

    }

    @Override
    protected void doConfigure() {

        super.doConfigure();

        final LoggerConfig rootLogger = getRootLogger();

        final Map<String, Appender> appenderMap = rootLogger.getAppenders();

        if (MainClass.DEBUG) {

            rootLogger.addAppender(appenderMap.get("Console"), Level.ALL, null);

        } else {

            rootLogger.addAppender(appenderMap.get("Mail"), Level.ERROR, null);

        }

    }
}

现在,在运行此操作并在调用Logging API之前调用ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory())之前,我将以

的形式输出到控制台
ERROR StatusLogger Reconfiguration failed: No configuration found for 'someNumbersAndChars' at 'null' in 'null'

在调试时,我发现这是在我第一次获得Logger时打印出来的。这样做的原因是,如果提供了自定义ConfigurationFactory,则由ConfigurationFactory.getConfiguration(LoggerContext, String, URI)的私有子类ConfigurationFactory(这是默认工厂)实施Factory )将被ConfigurationFactory的实施覆盖。

ConfigurationFactory的实现只是返回null如果URI是这样,而ConfigurationFactory.Factory的实现仍会返回有效的配置。

(link to source)

我现在的第一个想法是在我的自定义工厂中覆盖ConfigurationFactory.getConfiguration()的这些重载,但必须有另一种方法,对吧? ;)

2 个答案:

答案 0 :(得分:3)

我通过调用

解决了这个问题
System.setProperty("log4j.configurationFactory", CustomConfigurationFactory.class.getName());

作为替代方法,使用此JVM启动参数:
-Dlog4j.configurationFactory=factory.CustomConfigurationFactory

而不是

ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory());

首次访问LogManager之前。

-

编辑:您还可以在文件log4j2.component.properties中配置此设置。

内容:

log4j.configurationFactory=factory.CustomConfigurationFactory

通过这样做,您可以确保在加载任何记录器类之前应用此设置,并避免类初始化顺序的潜在问题。

如果您在Log4j2源中查找org.apache.logging.log4j.util.PropertiesUtil的使用情况,您可以找到可以这种方式配置的所有设置。

-

在分析/调试问题时,我注意到我的ConfigurationFactory已创建,但未用于获取配置。

最后,我在docs中找到了这段话,这解释了所有内容(我们可能没有及早致电setConfigurationFactory):

  

在初始化期间,Log4j 2将搜索可用的ConfigurationFactories,然后选择要使用的ConfigurationFactories。选定的ConfigurationFactory创建Log4j将使用的配置。以下是Log4j如何找到可用的ConfigurationFactories:

     
      
  1. 可以使用要使用的ConfigurationFactory的名称设置名为“log4j.configurationFactory”的系统属性。
  2.   
  3. 可以使用要使用的ConfigurationFactory实例调用ConfigurationFactory.setConfigurationFactory(ConfigurationFactory)。 必须在对Log4j进行任何其他调用之前调用此方法。
  4.   
  5. 可以将ConfigurationFactory实现添加到类路径中,并将其配置为“ConfigurationFactory”类别中的插件。订单注释可用于指定找到多个适用的ConfigurationFactories时的相对优先级。
  6.   

答案 1 :(得分:0)

我认为这可能是由于您拥有@Order()而引起的。我找不到任何说明如何比较指定订单的文档,但是我相信优先选择使用的数字更高。默认XmlConfigurationFactory的订单为5( log4j 版本为 2.13.1 ),因此,如果将订单更改为6,则应根据需要获得工厂