【问题标题】:Creating log4j Async logger programmatically以编程方式创建 log4j 异步记录器
【发布时间】:2018-06-27 17:55:42
【问题描述】:

我正在使用 Log4J 2.10。

我正在尝试以编程方式创建异步 logger\appender。我需要两件事:

  1. 我应该能够在运行时指定日志文件的文件路径。
  2. 我需要在运行时指定模式。

我可以想出下面的代码。但我无法将 RollingFileAppender 添加到 AsyncAppender。网上有使用 AsyncAppender.wrap 的示例。但该 API 似乎不适用于 Log4J 2.10。

你知道我是怎么做到的吗?

void createLog4JLogger(final String logFilePath) {
    
    LoggerContext context = (LoggerContext) LogManager.getContext();
    final Configuration config = context.getConfiguration();

    final PatternLayout patternLayout = PatternLayout.newBuilder().withPattern(CONVERSION_PATTERN).withCharset(Charset.defaultCharset()).build();

    final RollingFileAppender fileAppender = 
            RollingFileAppender.newBuilder().withName(APPENDER_NAME).withLayout(patternLayout).withFileName(logFilePath).build();
    
    AppenderRef ref = AppenderRef.createAppenderRef(APPENDER_NAME, null, null);
    AppenderRef[] refs = new AppenderRef[] {ref};
    
    final AsyncAppender asyncAppender = AsyncAppender.newBuilder().setAppenderRefs(refs).setName(APPENDER_NAME).setConfiguration(config).build();
    
    LoggerConfig loggerConfig = LoggerConfig.createLogger(false, Level.INFO, LOGGER_NAME, LOGGER_NAME, refs, null, null, null);
    loggerConfig.addAppender(asyncAppender, null, null);
    
    
    config.addAppender(asyncAppender);
    config.addLogger(LOGGER_NAME, loggerConfig);
    
    
    context.updateLoggers(config);
    
    final Logger logger = LogManager.getContext().getLogger(LOGGER_NAME);
    
    
    logger.info("HELLO_WORLD");
    
}

【问题讨论】:

    标签: java asynchronous logging log4j


    【解决方案1】:

    您可以使用以下代码在 log4j 2 中创建异步记录器。

    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    final Configuration config = ctx.getConfiguration();
    Layout layout = PatternLayout.newBuilder().withConfiguration(ctx.getConfiguration()).withPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - test %msg%n").build();
    Appender appender = FileAppender.newBuilder().withFileName("logs/test.log").setLayout(layout)
                        .setConfiguration(config).setName("TestApp").build();
    AppenderRef ref = AppenderRef.createAppenderRef("TestApp",Level.INFO, null);
    
    config.addAppender(appender);
    appender.start();
    AppenderRef[] refs = new AppenderRef[] {ref};
    LoggerConfig loggerConfig= AsyncLoggerConfig.createLogger(true, Level.INFO, "test","test", refs, null, config, null);
    loggerConfig.addAppender(appender, Level.INFO, null);
    config.addLogger("test", loggerConfig);
    loggerConfig.start();
    

    【讨论】:

      【解决方案2】:

      我需要使用没有配置文件的多线程 log4j 记录器。所以我最终将来自多个来源的代码(答案中的引用)放在一起。它已经工作了几年(抱歉延迟回复)。也许对其他人有用:

      创建记录器的类:

      class MyCustomLogger {
      private static Logger createLog4JLogger(final String logFilePath, final String logLevel) {
      
          try {
              final Level level = (null != logLevel && 0 == logLevel.toLowerCase().compareTo(DEBUG_MODE_STRING)) ? Level.DEBUG : Level.INFO;
      
              ConfigurationFactory.setConfigurationFactory(new LogCustomConfigurationFactory(logFilePath, level)); // This must be called before any other calls to Log4j
      
              dumpStringToSysOut("created configuration factory");
      
              Logger logger = LogManager.getLogger();
      
              dumpStringToSysOut("logger is " + ((null == logger) ? "null" : "not null"));
      
              return logger;
          } catch(Exception e) {
              e.printStackTrace();
          }
      
          return null;
      }
      

      }

      自定义配置工厂:

            import java.io.File;
        import java.net.URI;
      
        import org.apache.logging.log4j.Level;
        import org.apache.logging.log4j.core.LoggerContext;
        import org.apache.logging.log4j.core.appender.ConsoleAppender;
        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.builder.api.AppenderComponentBuilder;
        import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
        import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
        import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
        import org.apache.logging.log4j.core.config.builder.api.LayoutComponentBuilder;
        import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
        import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
        import org.apache.logging.log4j.core.config.plugins.Plugin;
      
        @Plugin(name = "LogCustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
        @Order(50)
        public class LogCustomConfigurationFactory extends ConfigurationFactory {
      
           private final String _logFilePath;
           private final Level _level;
      
           public LogCustomConfigurationFactory(final String logFilePath, final Level level) {
              _logFilePath = logFilePath;
              _level = level;
           }
      
           public LogCustomConfigurationFactory() {
              _logFilePath = System.getenv("TEMP") + File.separator + "my.log";
              _level = Level.INFO;
           }
      
      
          //https://github.com/LMAX-Exchange/disruptor/releases   
          private static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder, final String logFilePath, final Level level) {
            builder.setConfigurationName(name);
      
            //https://stackoverflow.com/questions/34904304/how-to-properly-create-a-rollingfileappender-with-appendercomponentbuilder-in-lo
            //ConfigurationBuilder< BuiltConfiguration > builder =
            //        ConfigurationBuilderFactory.newConfigurationBuilder();
      
            builder.setStatusLevel(Level.ERROR);
            builder.setConfigurationName("RollingBuilder");
            // create the console appender
            AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
                    ConsoleAppender.Target.SYSTEM_OUT);
            appenderBuilder.add(builder.newLayout("PatternLayout").
                    addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
            builder.add( appenderBuilder );
      
            LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
                    .addAttribute("pattern", "[%d{dd-MM-yyyy HH:mm:ss}] [%t] [%p] %m%n");
            ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
                    .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
                    .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
            appenderBuilder = builder.newAppender("rolling", "RollingFile")
                    .addAttribute("fileName", logFilePath)
                    .addAttribute("filePattern", "C:\\Temp\\rolling-%d{MM-dd-yy}.log.gz")
                    .add(layoutBuilder)
                    .addComponent(triggeringPolicy)
      
                    ;
            builder.add(appenderBuilder);
      
            // create the new logger
            //builder.add( builder.newLogger( "Logger", Level.DEBUG )
            //        .add( builder.newAppenderRef( "rolling" ) )
            //        .addAttribute( "additivity", false ) );
      
            //builder.add( builder.newRootLogger( Level.DEBUG )
      
            builder.add( builder.newAsyncRootLogger( level )
                    .add( builder.newAppenderRef( "rolling" ) ) );
            return builder.build();
            //Configurator.initialize(builder.build());    
      
      
            //https://stackoverflow.com/questions/43145250/how-to-configure-log4j-2-to-asynchonous-mode-programmatically?noredirect=1&lq=1
            /*
            AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
                addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
            appenderBuilder.add(builder.newLayout("PatternLayout").
                //addAttribute("pattern", "[%d{dd-MM-yyyy HH:mm:ss}] [%t] [%p] [%c] - %m%n %level: %msg%n"));
                 addAttribute("pattern", "[%d{dd-MM-yyyy HH:mm:ss}] [%t] [%p] [%c] - %m%n"));
      
            builder.add(appenderBuilder);
      
            RootLoggerComponentBuilder rootLoggerBuilder = builder.newAsyncRootLogger(Level.DEBUG); // use newAsyncRootLogger instead of newRootLogger 
            rootLoggerBuilder.add(builder.newAppenderRef("Stdout"));
      
            builder.add(rootLoggerBuilder);
            return builder.build();*/
          }
      
          @Override
          public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
            return getConfiguration(loggerContext, source.toString(), null);
          }
      
          @Override
          public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
            ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
            return createConfiguration(name, builder, _logFilePath, _level);
          }
      
          @Override
          protected String[] getSupportedTypes() {
            return new String[]{"*"};
          }
        }
      

      【讨论】:

        猜你喜欢
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-28
        相关资源
        最近更新 更多