【问题标题】:How to configure Logger Programmatically in log4j2.02?如何在 log4j2.02 中以编程方式配置 Logger?
【发布时间】:2014-12-27 10:26:32
【问题描述】:

我想使用 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 公开,主要用于单元测试。

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

【问题讨论】:

    标签: java log4j


    【解决方案1】:

    如果我只是回应您的要求,我可以建议三个选项。我将第一个用于一种引导记录器配置;但是我认为第二个一开始是必要的。您的第三个选择似乎很麻烦,因为您需要调用不同的 log4j API-s 来进行配置。

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

    1. 在 JAR 文件的资源中创建一个“最小”或“默认”log4j.properties 文件。然后声明一些静态...

      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 路线。

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

    我使用#1 的方式是通过资源文件建立默认/引导记录器配置,该资源文件本身被包装到 JAR 文件中。您可以“稍后”重新配置,而此选项为您提供极简的启动或引导配置。在早期阶段,我发现事情没有(还)被记录,因为记录器初始化尚未在嵌入式应用程序上发生。因此,从那以后,我将引导程序(或默认)的简单选项作为基本选项。希望这会有所帮助。

    【讨论】:

      【解决方案2】:

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

      该解决方案避免使用核心实现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 
      

      【讨论】:

      • 如果您打算遮蔽记录器 jar 以将其完全隐藏,请添加为第一行:LogManager.setFactory(new Log4jContextFactory());现在您还可以使用阴影过滤器省略所有配置和属性文件。
      【解决方案3】:

      使用最新版本的log4j2,都创建类似的API

      PatternLayout.createLayout, 
      FileAppender.createAppender, 
      LoggerConfig.createLogger 
      

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

      【讨论】:

      • 有什么例子可以参考@Dev?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 2014-12-15
      • 2011-02-17
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多