自定义ConfigurationFactory结合log4j2中的配置文件

Mak*_*kk0 5 java debugging logging log4j2

我正在尝试通过将配置文件与程序配置相结合初始化Log4j

我遵循了手册(尽管它的语法不太正确并且已经过时了),导致出现了以下类:

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;

    }

}
Run Code Online (Sandbox Code Playgroud)

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);

        }

    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当运行此命令并ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory())在调用Logging API之前调用时,我将以以下形式获取输出到控制台

ERROR StatusLogger Reconfiguration failed: No configuration found for 'someNumbersAndChars' at 'null' in 'null'
Run Code Online (Sandbox Code Playgroud)

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

如果URI如此,and ConfigurationFactory的实现只是返回null,而ConfigurationFactory.Factory的实现仍然返回有效的配置。

(链接到源)

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

Fre*_*ger 5

我通过调用解决了这个问题

System.setProperty("log4j.configurationFactory", CustomConfigurationFactory.class.getName());
Run Code Online (Sandbox Code Playgroud)

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

代替

ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory());
Run Code Online (Sandbox Code Playgroud)

LogManager第一次访问之前。

——

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

内容:

log4j.configurationFactory=factory.CustomConfigurationFactory
Run Code Online (Sandbox Code Playgroud)

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

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

——

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

最后我在文档中找到了这段话,它解释了这一切(我们可能没有setConfigurationFactory提前打电话):

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

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