Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configure log4j2 programmatically using ConfigurationFactory

I'm trying to configure and set up Log4j2 only through using ConfigurationFactory and this reference. The code I'm using is as follows:

public class LoggingConfiguration {

    public static final String PATTERN_LAYOUT = "[%d] [%t] [%-5level] - %msg (%logger{1}:%L) %n%throwable";
    public static final String LOG_FILE_NAME = "app.log";
    public static final String LOG_FILE_NAME_PATTERN = LOG_FILE_NAME + "-yyyy.MM.dd";

    static {
        ConfigurationFactory.setConfigurationFactory(new Log4j2ConfigurationFactory());
    }

    /**
     * Just to make JVM visit this class to initialize the static parts.
     */
    public static void configure() {
    }

    @Plugin(category = "ConfigurationFactory", name = "Log4j2ConfigurationFactory")
    @Order(0)
    public static class Log4j2ConfigurationFactory extends ConfigurationFactory {

        @Override
        protected String[] getSupportedTypes() {
            return null;
        }

        @Override
        public Configuration getConfiguration(ConfigurationSource source) {
            return new Log4j2Configuration();
        }

        @Override
        public Configuration getConfiguration(String name, URI configLocation) {
            return new Log4j2Configuration();
        }

    }

    private static class Log4j2Configuration extends DefaultConfiguration {

        public Log4j2Configuration() {
            setName("app-log4j2");
            String root = System.getProperty("APP_ROOT", "/tmp");
            if (!root.endsWith("/")) {
                root += "/";
            }
                            // MARKER
            Layout<? extends Serializable> layout = PatternLayout.createLayout(PATTERN_LAYOUT, null, null, null, null);

            String oneDay = TimeUnit.DAYS.toMillis(1) + "";
            String oneMB = (1024 * 1024) + "";
            final TimeBasedTriggeringPolicy timeBasedTriggeringPolicy = TimeBasedTriggeringPolicy.createPolicy(oneDay,
                    "true");
            final SizeBasedTriggeringPolicy sizeBasedTriggeringPolicy = SizeBasedTriggeringPolicy.createPolicy(oneMB);
            final CompositeTriggeringPolicy policy = CompositeTriggeringPolicy.createPolicy(timeBasedTriggeringPolicy,
                    sizeBasedTriggeringPolicy);
            final DefaultRolloverStrategy strategy = DefaultRolloverStrategy.createStrategy("7", "1", null,
                    Deflater.DEFAULT_COMPRESSION + "", this);
            Appender appender = RollingFileAppender.createAppender(root + LOG_FILE_NAME, LOG_FILE_NAME_PATTERN, "true",
                    "app-log-file-appender", "true", "true", policy, strategy, layout, null, null, null, null, null);
            addAppender(appender);
            getRootLogger().addAppender(appender, Level.INFO, null);
        }
    }

}

Note that

  • it extends BaseConfiguration that already configures console by default
  • it tries to add a rolling file appender to the root logger

I get the following exception:

Exception in thread "main" java.lang.IllegalStateException: Pattern does not contain a date
    at org.apache.logging.log4j.core.appender.rolling.PatternProcessor.getNextTime(PatternProcessor.java:91)
    at org.apache.logging.log4j.core.appender.rolling.TimeBasedTriggeringPolicy.initialize(TimeBasedTriggeringPolicy.java:49)
    at org.apache.logging.log4j.core.appender.rolling.CompositeTriggeringPolicy.initialize(CompositeTriggeringPolicy.java:43)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.<init>(RollingFileManager.java:58)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:297)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager$RollingFileManagerFactory.createManager(RollingFileManager.java:267)
    at org.apache.logging.log4j.core.appender.AbstractManager.getManager(AbstractManager.java:71)
    at org.apache.logging.log4j.core.appender.OutputStreamManager.getManager(OutputStreamManager.java:65)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.getFileManager(RollingFileManager.java:78)
    at org.apache.logging.log4j.core.appender.RollingFileAppender.createAppender(RollingFileAppender.java:175)
    at com.narmnevis.papyrus.LoggingConfiguration$Log4j2Configuration.<init>(LoggingConfiguration.java:79)
    at com.narmnevis.papyrus.LoggingConfiguration$Log4j2ConfigurationFactory.getConfiguration(LoggingConfiguration.java:55)
    at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:377)
    at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:149)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:85)
    at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:34)
    at org.apache.logging.log4j.LogManager.getContext(LogManager.java:200)
    at org.slf4j.helpers.Log4jLoggerFactory$PrivateManager.getContext(Log4jLoggerFactory.java:104)
    at org.slf4j.helpers.Log4jLoggerFactory.getContext(Log4jLoggerFactory.java:90)
    at org.slf4j.helpers.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:46)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:270)
    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:281)
    at com.narmnevis.papyrus.Main.<init>(Main.java:12)
    at com.narmnevis.papyrus.Main.main(Main.java:21)

If I comment out the code after MARKER in above code, it works but it seems that I'm missing something to configure a rolling file appender. What should I do to fix this?

like image 830
nobeh Avatar asked Jan 02 '14 16:01

nobeh


People also ask

How do I change the Log4j2 properties at runtime?

Use LogManager. resetConfiguration(); to clear the current config and configure it again. Another approach is to build a new appender and replace the old one with it (most appenders don't support changing their config).

What is Rootlogger in Log4j2?

This concept is known as Logger Hierarchy. Logger Hierarchy is made up of set of LoggerConfig objects with a parent-child relationship. The topmost element in every Logger Hierarchy is the Root Logger. If Log4j2 doesn't find the configuration file, only Root Logger will be used for logging with logging level as ERROR.

What is CTX in log4j?

The ThreadContext allows applications to store information either in a Map or a Stack. The MDC is managed on a per thread basis. To enable automatic inheritance of copies of the MDC to newly created threads, enable the "isThreadContextMapInheritable" Log4j system property.


1 Answers

In log4j 2.x you have to specify the date format in this way

public static final String LOG_FILE_NAME_PATTERN = LOG_FILE_NAME + "-%d{dd-MM-yyy}";
  • % marks the beginning of a format
  • d means that it is a date format (you can also use date)
  • within the curly braces {} you define the formatter's options. In this case the date format. You can use everything that a SimpleDateFormat would accept.

In addition you can also use:

  • %d{ABSOLUTE} -> HH:mm:ss,SSS
  • %d{COMPACT} -> yyyyMMddHHmmssSSS
  • %d{DATE} -> dd MMM yyyy HH:mm:ss,SSS
  • %d{ISO8601_BASIC} -> yyyyMMdd HHmmss,SSS
  • %d{ISO8601} -> yyyy-MM-dd HH:mm:ss,SSS

Note: This information is based on log4j 2.0-beta9 (the current release). Since it is a beta version it might change slightly.

like image 154
René Link Avatar answered Oct 22 '22 23:10

René Link