【问题标题】:How to configure log4j 2.x purely programmatically?如何纯粹以编程方式配置 log4j 2.x?
【发布时间】:2015-09-02 02:55:57
【问题描述】:

如何以编程方式配置log4j 2.3console appender pure(没有任何格式的配置文件)?

基本上我正在寻找这个1.x code 的2.x 版本。

然后我会在我的课程中使用

private static final Logger logger = LogManager.getLogger();
// 
    // some method
       logger.debug(someString);

没有任何配置我(如预期)面临

ERROR StatusLogger 找不到 log4j2 配置文件。使用默认配置:仅将错误记录到控制台。

虽然配置文件的用法似乎是properly documented,但我找不到一个简单的纯代码案例的好例子。

我得到的最接近的是this article,它仍然使用一个虚拟文件。

这是我最好的(虽然完全不成功)的镜头:

private static void configureLog4J() {
    PatternLayout layout = PatternLayout.createDefaultLayout();
    ConsoleAppender appender = ConsoleAppender.createDefaultAppenderForLayout(layout);
    LoggerConfig loggerConfig = new LoggerConfig();
    loggerConfig.addAppender(appender, DEBUG, null);
}

我错过了什么吗?

如果仍然是 RTFM 案例,请指出正确的方向。

【问题讨论】:

  • 直接log4j2,不用slf4j?
  • @SotiriosDelimanolis - 是的,这就是目的。
  • 直到最近,logback 也缺少纯程序化配置。见stackoverflow.com/questions/22335441/…。 .在那篇 SO 帖子中有一个 log4j2 链接,我永远无法使用我的 init 代码启动 log4j2,但最新的 logback 将允许您控制 init 进程。

标签: java log4j log4j2


【解决方案1】:
package com;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.config.AppenderRef;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;

import java.nio.charset.Charset;

public class MyLoggerTest  {

    public static void main(String[] args){
        LoggerContext context= (LoggerContext) LogManager.getContext();
        Configuration config= context.getConfiguration();

        PatternLayout layout= PatternLayout.createLayout("%m%n", null, null, Charset.defaultCharset(),false,false,null,null);
        Appender appender=ConsoleAppender.createAppender(layout, null, null, "CONSOLE_APPENDER", null, null);
        appender.start();
        AppenderRef ref= AppenderRef.createAppenderRef("CONSOLE_APPENDER",null,null);
        AppenderRef[] refs = new AppenderRef[] {ref};
        LoggerConfig loggerConfig= LoggerConfig.createLogger("false", Level.INFO,"CONSOLE_LOGGER","com",refs,null,null,null);
        loggerConfig.addAppender(appender,null,null);

        config.addAppender(appender);
        config.addLogger("com", loggerConfig);
        context.updateLoggers(config);

        Logger logger=LogManager.getContext().getLogger("com");
        logger.info("HELLO_WORLD");


    }
}

不确定这是否是您要查找的内容。这将创建一个默认配置并添加一个控制台记录器。但是,LogManager.getLogger() 不起作用,并且使用 LogManager.getContext().getLogger() 不允许记录器层次结构。老实说我不推荐编程方法,Log4j2 对它过敏。

【讨论】:

    【解决方案2】:

    这是 log4j 2.8 编程配置的完整示例。 它有 3 个附加程序:RollingFile、JDBC 和 SMTP。

    有1个类和2个属性配置文件,一个用于将类注册为log4j2配置工厂,另一个用于设置日志文件目录等属性。

    类 #1:MPLoggingConfiguration

    package com.websitester.config;
    
    import java.io.Serializable;
    import java.nio.charset.Charset;
    import java.util.zip.Deflater;
    
    import org.apache.logging.log4j.Level;
    import org.apache.logging.log4j.core.Appender;
    import org.apache.logging.log4j.core.Layout;
    import org.apache.logging.log4j.core.LoggerContext;
    import org.apache.logging.log4j.core.appender.RollingFileAppender;
    import org.apache.logging.log4j.core.appender.SmtpAppender;
    import org.apache.logging.log4j.core.appender.db.ColumnMapping;
    import org.apache.logging.log4j.core.appender.db.jdbc.ColumnConfig;
    import org.apache.logging.log4j.core.appender.db.jdbc.ConnectionSource;
    import org.apache.logging.log4j.core.appender.db.jdbc.DataSourceConnectionSource;
    import org.apache.logging.log4j.core.appender.db.jdbc.JdbcAppender;
    import org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy;
    import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
    import org.apache.logging.log4j.core.appender.rolling.OnStartupTriggeringPolicy;
    import org.apache.logging.log4j.core.appender.rolling.SizeBasedTriggeringPolicy;
    import org.apache.logging.log4j.core.appender.rolling.TriggeringPolicy;
    import org.apache.logging.log4j.core.config.AppenderRef;
    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.DefaultConfiguration;
    import org.apache.logging.log4j.core.config.LoggerConfig;
    import org.apache.logging.log4j.core.config.Order;
    import org.apache.logging.log4j.core.config.Property;
    import org.apache.logging.log4j.core.config.plugins.Plugin;
    import org.apache.logging.log4j.core.layout.HtmlLayout;
    import org.apache.logging.log4j.core.layout.PatternLayout;
    
    public class MPLoggingConfiguration {
    
        public static final String WEBSITESTER_LOGGER_NAME = "com.websitester";
        public static final String FILE_PATTERN_LAYOUT = "%n[%d{yyyy-MM-dd HH:mm:ss}] [%-5p] [%l]%n\t%m%n%n";
        public static final String LOG_FILE_NAME = "awmonitor.log";
        public static final String LOG_FILE_NAME_PATTERN = "awmonitor-%i.log";  
    
        /**
         * Just to make JVM visit this class to initialize the static parts.
         */
        public static void configure() {
        }
    
        @Plugin(category = ConfigurationFactory.CATEGORY, name = "MPConfigurationFactory")
        @Order(15)
        public static class MPConfigurationFactory  extends ConfigurationFactory {
            public static final String[] SUFFIXES = new String[] {".json", "*"};
    
            @Override
            protected String[] getSupportedTypes() {
                return SUFFIXES;
            }
    
            @Override
            public Configuration getConfiguration(LoggerContext arg0, ConfigurationSource arg1) {
                return new Log4j2Configuration(arg1);
            }
        }
    
        private static class Log4j2Configuration extends DefaultConfiguration {
    
            public Log4j2Configuration(ConfigurationSource source) {
                super.doConfigure();
                setName("mp-log4j2");
    
                String logFilePath = "/log/weblogic/wl-moniport/";
    
                // LOGGERS
                //      com.websitester
                AppenderRef[] refs = new AppenderRef[] {};
                Property[] properties = new Property[] {};
                LoggerConfig websitesterLoggerConfig = LoggerConfig.createLogger(true, Level.INFO, WEBSITESTER_LOGGER_NAME, "true", refs, properties, this, null);
                addLogger(WEBSITESTER_LOGGER_NAME, websitesterLoggerConfig);
    
    
                // APPENDERS
                final Charset charset = Charset.forName("UTF-8");
    
                //      MP ROLLING FILE
                TriggeringPolicy mpFileCompositePolicy = CompositeTriggeringPolicy.createPolicy(
                        SizeBasedTriggeringPolicy.createPolicy("3 M"),
                        OnStartupTriggeringPolicy.createPolicy(1));
                final DefaultRolloverStrategy mpFileRolloverStrategy = DefaultRolloverStrategy.createStrategy("9", "1", "max", Deflater.NO_COMPRESSION + "", null, true, this);
                Layout<? extends Serializable> mpFileLayout = PatternLayout.newBuilder()
                        .withPattern(FILE_PATTERN_LAYOUT)
                        .withPatternSelector(null)
                        .withConfiguration(this)
                        .withRegexReplacement(null)
                        .withCharset(charset)
                        .withAlwaysWriteExceptions(isShutdownHookEnabled)
                        .withNoConsoleNoAnsi(isShutdownHookEnabled)
                        .withHeader(null)
                        .withFooter(null)
                        .build();
                Appender mpFileAppender = RollingFileAppender.newBuilder()
                        .withAdvertise(Boolean.parseBoolean(null))
                        .withAdvertiseUri(null)
                        .withAppend(true)
                        .withBufferedIo(true)
                        .withBufferSize(8192)
                        .setConfiguration(this)
                        .withFileName(logFilePath + LOG_FILE_NAME)
                        .withFilePattern(logFilePath + LOG_FILE_NAME_PATTERN)
                        .withFilter(null)
                        .withIgnoreExceptions(true)
                        .withImmediateFlush(true)
                        .withLayout(mpFileLayout)
                        .withCreateOnDemand(false)
                        .withLocking(false)
                        .withName("error_file_web")
                        .withPolicy(mpFileCompositePolicy)
                        .withStrategy(mpFileRolloverStrategy)
                        .build();
                mpFileAppender.start();
                addAppender(mpFileAppender);
                getLogger(WEBSITESTER_LOGGER_NAME).addAppender(mpFileAppender, Level.DEBUG, null);
    
    
                // JDBC
                if (System.getProperty("log4jjdbcjndiName") != null){
                    ColumnConfig[] columnConfigs = new ColumnConfig[] {
                            ColumnConfig.newBuilder()
                            .setConfiguration(this)
                            .setName("DATED")
                            .setPattern(null)
                            .setLiteral(null)
                            .setEventTimestamp(true)
                            .setUnicode(false)
                            .setClob(false)
                            .build(),
                            ColumnConfig.newBuilder()
                            .setConfiguration(this)
                            .setName("LOGGER")
                            .setPattern("%logger")
                            .setLiteral(null)
                            .setEventTimestamp(false)
                            .setUnicode(false)
                            .setClob(false)
                            .build(),
                            ColumnConfig.newBuilder()
                            .setConfiguration(this)
                            .setName("LOG_LEVEL")
                            .setPattern("%level")
                            .setLiteral(null)
                            .setEventTimestamp(false)
                            .setUnicode(false)
                            .setClob(false)
                            .build(),
                            ColumnConfig.newBuilder()
                            .setConfiguration(this)
                            .setName("MESSAGE")
                            .setPattern("%message")
                            .setLiteral(null)
                            .setEventTimestamp(false)
                            .setUnicode(false)
                            .setClob(false)
                            .build(),
                            ColumnConfig.newBuilder()
                            .setConfiguration(this)
                            .setName("NODE")
                            .setPattern("" + System.getProperty("log4jmpserverid"))
                            .setLiteral(null)
                            .setEventTimestamp(false)
                            .setUnicode(false)
                            .setClob(false)
                            .build()
                    };
                    ConnectionSource dataSourceConnectionSource = DataSourceConnectionSource.createConnectionSource(System.getProperty("log4jjdbcjndiName"));
                    if (dataSourceConnectionSource != null){
                        Appender jdbcAppender = JdbcAppender.newBuilder()
                                .setBufferSize(0)
                                .setColumnConfigs(columnConfigs)
                                .setColumnMappings(new ColumnMapping[]{})
                                .setConnectionSource(dataSourceConnectionSource)
                                .setTableName("MTDTLOGS")
                                .withName("databaseAppender")
                                .withIgnoreExceptions(true)
                                .withFilter(null)
                                .build();
                        jdbcAppender.start();
                        addAppender(jdbcAppender);
                        getLogger(WEBSITESTER_LOGGER_NAME).addAppender(jdbcAppender, Level.WARN, null);
                    }
                };
    
                // SMTP
                if (System.getProperty("log4jemailSubject") != null){
                    if (System.getProperty("log4jemailLevel").equalsIgnoreCase("error")) {
                        Layout<? extends Serializable> mpHtmlLayout = HtmlLayout.createLayout(false, "Monitor de Portales", null, null, "x-small", null);
    
                        Appender smtpAppender = SmtpAppender.createAppender(
                                this,
                                "SMTP",
                                System.getProperty("log4jemailTo"), 
                                System.getProperty("log4jemailcc"), 
                                System.getProperty("log4jemailbcc"), 
                                System.getProperty("log4jemailFrom"), 
                                System.getProperty("log4jemailreplyTo"), 
                                System.getProperty("log4jemailSubject"), 
                                System.getProperty("log4jemailProtocol"), 
                                System.getProperty("log4jemailHost"), 
                                System.getProperty("log4jemailPort"), 
                                System.getProperty("log4jemailUserName"), 
                                System.getProperty("log4jemailPassword"), 
                                "false", 
                                "50", 
                                mpHtmlLayout, 
                                null, 
                                "true");
                        smtpAppender.start();
                        addAppender(smtpAppender);
                        getLogger(WEBSITESTER_LOGGER_NAME).addAppender(smtpAppender, Level.ERROR, null);
                    }
                }
            }
        }
    }
    

    配置文件:src/main/resources/log4j2.component.properties

    log4j.configurationFactory=com.websitester.config.MPLoggingConfiguration$MPConfigurationFactory
    log4j.configurationFile=log4j2websitester.json
    

    配置文件:src/main/resources/log4j2websitester.json

    {"logFilePath" : "/log/weblogic/wl-moniport/"}
    

    在我的例子中,我在其他类中设置了所有属性(通过 System.getProperty 在 MPLoggingConfiguration 中访问),例如:

    System.setProperty("log4jjdbcjndiName", "weblogic-monitor");
    

    当您更改了某些属性并想要重新配置 log4j2 时,您必须进行此调用:

    final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
    ctx.reconfigure();
    

    希望对你有帮助

    【讨论】:

    • ERROR StatusLogger 找不到 log4j2 配置文件。使用默认配置:仅将错误记录到控制台。设置系统属性“log4j2.debug”以显示 Log4j2 内部初始化日志......无法正确获取配置。请帮忙
    • 我编辑响应,更改第一个配置文件,包括“configurationFile”属性并包括新配置文件的内容。
    • 这不再适用于 2.11.x API - 您需要使用 ConfigurationBuilder baeldung.com/log4j2-programmatic-config
    • 似乎连接源仍然依赖于配置文件。似乎找不到以编程方式完全配置 JdbcAppender 的方法。
    【解决方案3】:

    您可以在 log4j 中自定义您自己的 ConfigurationFactory。 请参考https://logging.apache.org/log4j/2.x/manual/customconfig.html。它似乎可以满足您的需求。


    对此感到抱歉。这种方式是否满足您的需求?我只是测试了一下,虽然还是输出了你上面提到的错误信息,但运行良好。

        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        final Configuration config = ctx.getConfiguration();
        Layout<? extends Serializable> layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
            null,true, true,null,null);
    
        Appender appender = FileAppender.createAppender("/tmp/log4jtest.txt", "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", Level.INFO, "org.apache.logging.log4j",
            "true", refs, null, config, null );
        loggerConfig.addAppender(appender, null, null);
        config.addLogger("simpleTestLogger", loggerConfig);
        ctx.updateLoggers();
    
    
        Logger l = ctx.getLogger("simpleTestLogger");
        l.info("message of info level shoud be output properly");
        l.error("error message");
    

    【讨论】:

    • 我相信你误解了我的问题。我在问如何从头开始创建简单的配置,不依赖于任何配置文件的存在。
    • 我需要将ConsoleAppender 配置为在我的主代码中使用LogManager.getLogger() 时不会出现问题。
    • 第一次转换为 LoggerContext 似乎是多余的,因为该方法已经返回一个。但是 LoggerContext 也没有一个叫做 getConfiguration() 的方法。
    • @Trejkaz log4j2中有两个LoggerContext定义:一个是接口,一个是类。强制转换是进入该类所必需的,该类确实有一个 getConfiguration() 方法。
    【解决方案4】:

    如果你想要它用于控制台附加程序,如果你使用 maven,有一个非常简单的方法,只需将这 2 个依赖项放在你的 pom.xml 中,所有东西都会打印在你的控制台上。什么都不需要...根本没有 log4j.properties 文件。 slf4j 扩展了 log4j 并且有很多丰富的功能。

              <dependency>
                     <groupId>org.slf4j</groupId>
                     <artifactId>slf4j-api</artifactId>
                     <version>1.7.5</version>
                     <scope>compile</scope>
              </dependency>
    
              <dependency>
                     <groupId>org.slf4j</groupId>
                     <artifactId>slf4j-simple</artifactId>
                     <version>1.7.5</version>
              </dependency>
    

    【讨论】:

    • 添加诸如“slf4j”之类的其他依赖项会在项目的长期运行中导致额外的维护开销。
    【解决方案5】:

    documentation 推荐使用 builder api 进行编程配置。使用此 api,您的 configureLog4J() 方法可能如下所示:

    public static void configureLog4J() {
      ConfigurationBuilder<BuiltConfiguration> builder =
          ConfigurationBuilderFactory.newConfigurationBuilder();
    
      // configure a console appender
      builder.add(
          builder.newAppender("stdout", "Console")
              .add(
                  builder.newLayout(PatternLayout.class.getSimpleName())
                      .addAttribute(
                          "pattern",
                          "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
                      )
              )
      );
    
      // configure the root logger
      builder.add(
          builder.newRootLogger(Level.INFO)
              .add(builder.newAppenderRef("stdout"))
      );
    
      // apply the configuration
      Configurator.initialize(builder.build());
    
    }
    

    现在,诀窍是 - 而且手册没有足够清楚地说明 - 那 此静态初始化方法将在之前调用 LogManager.getLogger().

    对于一个最小的工作示例,您可以像这样使用静态初始化块

    private static final Logger log;
    
    static {
      configureLog4J();
      log = LogManager.getLogger(MyAwesomeClass.class);
    }
    

    也就是说,以编程方式配置日志记录对任何人来说都不是一个好主意 不平凡的项目:您每次都必须重新编译、测试和发布您的代码 您想暂时增加某些记录器上的日志级别以进行诊断 生产问题。因此我强烈建议不要使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 2013-05-18
      • 1970-01-01
      • 1970-01-01
      • 2016-11-20
      • 2014-12-15
      • 2011-02-17
      相关资源
      最近更新 更多