我试图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
的实现仍会返回有效的配置。
我现在的第一个想法是在我的自定义工厂中覆盖ConfigurationFactory.getConfiguration()
的这些重载,但必须有另一种方法,对吧? ;)
答案 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:
- 可以使用要使用的ConfigurationFactory的名称设置名为“log4j.configurationFactory”的系统属性。
- 可以使用要使用的ConfigurationFactory实例调用ConfigurationFactory.setConfigurationFactory(ConfigurationFactory)。 必须在对Log4j进行任何其他调用之前调用此方法。
- 可以将ConfigurationFactory实现添加到类路径中,并将其配置为“ConfigurationFactory”类别中的插件。订单注释可用于指定找到多个适用的ConfigurationFactories时的相对优先级。
醇>
答案 1 :(得分:0)
我认为这可能是由于您拥有@Order()
而引起的。我找不到任何说明如何比较指定订单的文档,但是我相信优先选择使用的数字更高。默认XmlConfigurationFactory
的订单为5( log4j 版本为 2.13.1 ),因此,如果将订单更改为6,则应根据需要获得工厂