Java 如何在log4j2.02中以编程方式配置记录器?

Java 如何在log4j2.02中以编程方式配置记录器?,java,log4j,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" 我找到了这个答案: 但是Logger#addAppender的文档说: 此方法不是通过公共API公开的,

我想使用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"
我找到了这个答案:

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


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

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

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

  • 在您的资源中为JAR文件创建一个“minimal”或“default”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 );
    }
    
  • 将配置写入StreamWriter,而不是将文件放入JAR中,然后将流作为StringReader提供给日志配置器,并使用上面的示例(或多或少)

  • 您可以使用进行日志配置,而不是直接写入Log4j。我去过的大多数地方都喜欢SLF4J路线

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

    我使用#1的方式是通过resources文件建立默认/引导记录器配置,该文件本身被包装到JAR文件中。您可以“以后”重新配置,而此选项为您提供了最低限度的启动或引导配置。在早期阶段,我发现事情还没有被记录下来,因为记录器初始化还没有在嵌入式应用上发生。因此,我一直将引导(或默认)的简单选项作为基本选项。希望这有帮助。

    显示了一个示例:通过编程方式添加到当前配置中

    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();
    
    有了这些限制:

  • 如果更改了配置文件,将重新加载配置,手动更改将丢失
  • 修改正在运行的配置需要同步所有被调用的方法(addAppender和addLogger)
  • 此解决方案避免了使用core实现中的方法
    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 
    

    使用最新版本的
    log4j2
    ,所有的API都像

    PatternLayout.createLayout, 
    FileAppender.createAppender, 
    LoggerConfig.createLogger 
    

    如果您已弃用,最好使用自定义日志
    ConfigurationFactory
    ConfigurationBuilder
    以编程方式定义日志配置。

    如果您计划对记录器jar进行着色以完全隐藏它,请添加为第一行:LogManager.setFactory(新的Log4jContextFactory());现在,您还可以使用阴影过滤器省略所有配置和属性文件?