'The presence of : character in filePattern causes Illegal Char error in RollingFileAppender (log4j2) when configuring programatically

In log4j2.xml when defining the RollingFileAppender, it works fine. Programatically its throwing the error. XML file -

  <RollingFile name="LogToRollingFile" fileName="logs/app.log"
                     filePattern="logs/$${date:yyyy-MM-dd-HH-mm}/app_%d{yyyy-MM-dd-HH-mm}_%i.log">

Java Code trying to replicate the same.

final RollingFileAppender rollingFileAppender = RollingFileAppender.newBuilder()
                    .setName("RollingFileAppenderFor"+fileName)
                    .withFileName("logs/"+ fileName+".log")
                    .withFilePattern("logs/$${date:yyyy-MM-dd-HH-mm}/"+ fileName +"-%d{yyyy-MM-dd-HH-mm}-%i.log.gz")
                    .withAppend(true)
                    .setConfiguration(config)
                    .setLayout(layout)
                    .withPolicy(CompositeTriggeringPolicy.createPolicy(timeBasedTriggeringPolicy,sizeBasedTriggeringPolicy))
                    .withStrategy(defaultRolloverStrategy)
                    .build();

Causes the following error.

2022-04-11 23:20:55,164 main ERROR An exception occurred processing Appender RollingFileAppenderForMephisto java.nio.file.InvalidPathException: Illegal char <:> at index 11: logs\${date:yyyy-MM-dd-HH-mm}
    at java.base/sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
    at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
    at java.base/sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
    at java.base/sun.nio.fs.WindowsPath.parse(WindowsPath.java:92)
    at java.base/sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:232)
    at java.base/java.io.File.toPath(File.java:2387)
    at org.apache.logging.log4j.core.appender.rolling.AbstractRolloverStrategy.getEligibleFiles(AbstractRolloverStrategy.java:121)
    at org.apache.logging.log4j.core.appender.rolling.AbstractRolloverStrategy.getEligibleFiles(AbstractRolloverStrategy.java:95)
    at org.apache.logging.log4j.core.appender.rolling.AbstractRolloverStrategy.getEligibleFiles(AbstractRolloverStrategy.java:86)
    at org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy.purgeAscending(DefaultRolloverStrategy.java:414)
    at org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy.purge(DefaultRolloverStrategy.java:401)
    at org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy.rollover(DefaultRolloverStrategy.java:530)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.rollover(RollingFileManager.java:502)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.rollover(RollingFileManager.java:392)
    at org.apache.logging.log4j.core.appender.rolling.RollingFileManager.checkRollover(RollingFileManager.java:308)
    at org.apache.logging.log4j.core.appender.RollingFileAppender.append(RollingFileAppender.java:311)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:542)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:500)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:483)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
    at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2017)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1983)
    at org.apache.logging.log4j.spi.AbstractLogger.log(AbstractLogger.java:1652)
    at mcoc.ChampionLogger.addLoggerWithModificationAndLog(ChampionLogger.java:137)
    at mcoc.Test3.main(Test3.java:8)

Is there anything I can do for this, is there a replacement for the : character in here.



Solution 1:[1]

Please read Log4j difference between dollar and percent patterns in layout for more details. Not all claims in the original answer are factually correct (and might lead to surprising behavior).


A double $ character will escape the second dollar character and make it a literal dollar character in your ouput.

Format the date as %d{...} and not $${date:...} (you can also try ${date:...}, note the single dollar):

  <RollingFile
      name="LogToRollingFile"
      fileName="logs/app.log"
      filePattern="logs/%d{yyyy-MM-dd-HH-mm}/app_%d{yyyy-MM-dd-HH-mm}_%i.log">

As for why the documentation mixes both %d and ${date:} in a single example, I don't know.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1