Answering this this question about log4j2 left me more confused than enlightened.
There seem to be several ways of specifying the current date (with custom format) in log4j2 configuration files:
(Interestingly, the log4j2 docs consistently use $${date:...}
in their examples, but doubling the dollar character should escape it and make it a literal dollar character followed by a curly brace and the word "date", a colon, the format, and the closing brace.)
What's the difference between one form or the other, if there is a difference? When should one used over the other?
Is there a difference when used together in a single value? The examples contain the following:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
<Properties>
<Property name="baseDir">logs</Property>
</Properties>
<Appenders>
<!-- HERE: -->
<RollingFile name="RollingFile" fileName="${baseDir}/app.log"
filePattern="${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}.log.gz">
<PatternLayout pattern="%d %p %c{1.} [%t] %m%n" />
<CronTriggeringPolicy schedule="0 0 0 * * ?"/>
<DefaultRolloverStrategy>
<Delete basePath="${baseDir}" maxDepth="2">
<IfFileName glob="*/app-*.log.gz" />
<IfLastModified age="P60D" />
</Delete>
</DefaultRolloverStrategy>
</RollingFile>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="RollingFile"/>
</Root>
</Loggers>
</Configuration>
$${date:yyyy-MM}
, but only a single dollar with ${baseDir}
?${date:yyyy-MM}
and %d{MM-dd-yyyy}
and not %d{yyyy-MM}
or ${date:MM-dd-yyyy}
?Who can clear the confusion?
Pattern placeholders like %d{...}
can be used in:
pattern
property of a pattern layout (cf. documentation) and by extension in the pattern
resolver of a JSON Template Layout (cf. documentation). These patterns are replaced with a property of the LogEvent
being logger,filePattern
property of a rolling file appender (just %i
and %d
). These patterns are replaced with the index and date pattern of the archived log file being created.Lookup placeholders ${type:key}
on the other hand can be used everywhere in your configuration file and are replaced eagerly when the file is read (cf. lookups). Therefore the fileName
property of your rolling file appender will have logs/app.log
as value.
There is however a second application for lookups: some properties, including all those that accept %
patterns, accept ${...}
lookups that will be evaluated at a later time. In order to prevent the evaluation of those lookups at configuration time, you need to escape $
as $$
.
That is why the ${baseDir}/$${date:yyyy-MM}/app-%d{yyyy-MM-dd}.log.gz
string in your configuration file is:
logs/${date:yyyy-MM}/app-%{yyyy-MM-dd}.log.gz
at configuration time,logs/2022-04/app-2022-04-16.log.gz
if a rollover occurs today.If you were to use ${date:yyyy-MM}
instead of $${date:yyyy-MM}
all log files would be (until reconfiguration occurs) in the logs/2022-04
folder.
The difference between $${date:yyyy-MM-dd}
and %d{yyyy-MM-dd}
is specific to the rolling file appender: the appender needs to know how often should a rollover occur. It does so by analyzing the %d{...}
pattern. That is why in your configuration rollover occurs daily (%d{yyyy-MM-dd}
) and not monthly ($${date:yyyy-MM}
).
Another difference between those two is in the date they use: $${date:...}
uses the current date, while %d{...}
uses the date of the previous rollover. These might be off by one rolling period.