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

标签 java debugging logging log4j2

我正在尝试 Initialize Log4j by Combining Configuration File with Programmatic Configuration .

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

自定义配置工厂.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;

    }

}

自定义配置.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);

        }

    }
}

现在,在运行它并调用 ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory()) 之前调用 Logging API 时,我会以

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

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

如果 URI 是这样的话,ConfigurationFactory 的实现简单地返回 null,而 ConfigurationFactory.Factory 的实现仍然返回一个有效的配置.

(link to source)

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

最佳答案

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

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

During initialization, Log4j 2 will search for available ConfigurationFactories and then select the one to use. The selected ConfigurationFactory creates the Configuration that Log4j will use. Here is how Log4j finds the available ConfigurationFactories:

  1. A system property named "log4j.configurationFactory" can be set with the name of the ConfigurationFactory to be used.
  2. ConfigurationFactory.setConfigurationFactory(ConfigurationFactory) can be called with the instance of the ConfigurationFactory to be used. This must be called before any other calls to Log4j.
  3. A ConfigurationFactory implementation can be added to the classpath and configured as a plugin in the "ConfigurationFactory" category. The Order annotation can be used to specify the relative priority when multiple applicable ConfigurationFactories are found.

关于java - 自定义ConfigurationFactory结合log4j2中的配置文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44227758/

相关文章:

java - 如何使用换行参数

objective-c - 来自应用程序各处的 AQXMLParser 和 EXC_BAD_INSTRUCTION

objective-c - UIButton 使用 ARC 触及导致 EXC_BAD_ACCESS 的 IBAction

java - 我在 Netbeans 名称(DemoApp)中有一个项目,该项目的日志文件存储在哪里?

Java正确实现数学日志功能?

Java 比较对象 equals() 和compareTo() 返回不同的结果

java - 这个通用 Guice 绑定(bind)方法的 TypeLiteral 等价物有什么问题?

java - "src"和有什么区别? "con"和 "output"

javascript - 如何使用 VS Code 调试 Node.js 中的私有(private)类字段?

java - 从 log4j 1.2.17 迁移后的 log4j 2.2 问题