如何在log4j2.02中以编程方式配置Logger?

时间:2014-10-31 06:48:08

标签: java log4j

我想在没有任何配置文件的情况下使用log4j 。 我想要做的是:

logger = (Logger) LogManager.getLogger(this.getClass());
String pattern = "[%level] %m%n";
//do something to make this logger output to an local file "/xxx/yyy/zzz.log"

我找到了这个答案:Configuring Log4j Loggers Programmatically

但是Logger#addAppender的文档说: 此方法通过公共API公开,主要用于单元测试。

我不确定在我的代码中使用此方法是否正确,或者还有其他更好的解决方案来解决我的问题。

3 个答案:

答案 0 :(得分:23)

The official documentation显示了一个示例:以编程方式添加到当前配置

final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();

Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null, null,null, null);
Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true", "false", "false", "4000", layout, null, "false", null, config);
appender.start();
config.addAppender(appender);

AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
AppenderRef[] refs = new AppenderRef[] {ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j", "true", refs, null, config, null );
loggerConfig.addAppender(appender, null, null);
config.addLogger("org.apache.logging.log4j", loggerConfig);
ctx.updateLoggers();

有这些限制:

  1. 如果更改配置文件,将重新加载配置,手动更改将丢失。
  2. 对运行配置的修改要求调用所有被调用的方法(addAppender和addLogger)。
  3. 此解决方案避免使用核心实现org.apache.logging.log4j.core.Logger中的方法,并且避免了类似的脏转换:

    import org.apache.logging.log4j.Logger;
    
    Logger logger = (Logger) LogManager.getLogger(this.getClass());
    ((org.apache.logging.log4j.core.Logger) logger).addAppender(...); // Bypassing the public API 
    

答案 1 :(得分:2)

使用最新版本的log4j2,所有人都会创建像

这样的API
PatternLayout.createLayout, 
FileAppender.createAppender, 
LoggerConfig.createLogger 

已被弃用,最好使用自定义日志ConfigurationFactoryConfigurationBuilder以编程方式定义日志配置。

答案 2 :(得分:0)

如果我只是回应您的要求,我可以提出三种选择。我使用第一个用于一种bootstrap Logger配置;但是我认为第二个是必要的。您的第三个选择似乎很麻烦,因为您需要调用不同的log4j API来进行配置。

在Java的简单日志框架上使用Log4j ...

  1. 制作一个最小的'或者'默认' log4j.properties文件位于JAR文件的资源中。然后宣布一些静态......

    private static final  URL LOGGER_CONFIG_URL  = resolveConfigUrl();
       :
    
    private static URL  resolveConfigUrl(){
    
        URL url = LogConfig.class.getResource( LOGGER_CONFIG_NAME );
    
        if( null == url )  // Second chance, try for a file.
        {
            url = FileHelp.resolveUrlNameAsUrlToFile( LOGGER_CONFIG_NAME );
                      //-- Make this function with: url = tmpFile.toURI().toURL()
                      //   Plus appropriate try/catch and error checks.
          }
          return url;
    } 
    
    private static void  configureLogger(){
    
        BasicConfigurator.configure();
        PropertyConfigurator.configure( LOGGER_CONFIG_URL  );
        LOG.info( "Logging config done: " +  LOGGER_CONFIG_NAME );
    }
    
  2. 将您的配置写入StreamWriter而不是将文件放入JAR中,然后将Stream作为StringReader提供给日志配置器并使用上面的示例(或多或少)。

  3. 您可以使用slf4j API进行日志配置,而不是直接写入Log4j。大多数地方我更喜欢SLF4J路线。

  4. 就个人而言,我更喜欢选项#1;它易于维护。简单,您可以随时重新排序代码以接受/查找要首先加载的文件。您还可以考虑其他一些横向途径,例如在启动时以编程方式设置环境变量。这似乎是我的设计。

    我使用#1的方法是通过资源文件建立默认/引导记录器配置,该文件本身被包装到JAR文件中。您可以稍后重新配置 '而这个选项为您提供了极简主义的星形或自举配置。在早期阶段,我发现事情还没有被记录,因为记录器初始化还没有发生在嵌入式应用程序上。所以我保留了引导程序(或默认)的简单选项作为基础。希望这会有所帮助。