Q:

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?

A:

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.

