Search code examples
javatomcatlogginglog4jlog4j2

System property not being read by log4j2 -> lo4j1 bridge


I am working on a large java web-based project that is based on some older versions of Spring and Hibernate, and uses log4j 1.2x. Due to recent vulnerabilities found in log4j2, we have been directed to upgrade to the latest version of log4j2. I am trying to implement the log4j2 log4j1 bridge, so that I don't have to update all our logging code in the application. It is all working fine, except I cannot specify where to store the log files, because the log4j1 bridge appears to not support system properties. I am passing in a ${catalina.base} property when starting my tomcat server, but the log4j1 bridge uses the literal text rather than substituting the propery value.

My maven pom.xml

...
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.1</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-1.2-api</artifactId>
    <version>2.17.1</version>
</dependency>
...

The section of the log4j.xml file where I reference the system property:

log4j-dev.xml

...
<appender name="DAILY" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="${catalina.base}/logs/etl.log"/>
    <param name="DatePattern" value="'.'yyyy-MM-dd"/>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="GATEWAY: %p %d [%t] %c{1}.%M(%L) | %m%n"/>
    </layout>
</appender>
...

The setenv.bat entry where I define which log4j.xml to use:

-Dlog4j2.debug=true -Dlog4j.configuration=log4j-dev.xml

The properties shown in the tomcat log illustrating that the system property in question is being supplied to the log4j1 bridge

...
Command line argument: -Dlog4j2.debug=true
Command line argument: -Dlog4j.logDir=C:\dev\apache-tomcat-8.5.50\logs
Command line argument: -Dlog4j.configuration=log4j-dev.xml
Command line argument: -Dcatalina.base=C:\dev\apache-tomcat-8.5.50
Command line argument: -Dcatalina.home=C:\dev\apache-tomcat-8.5.50
Command line argument: -Djava.io.tmpdir=C:\dev\apache-tomcat-8.5.50\temp
...

And the part of the log that shows where the log file is successfully created and what path it is using:

...
DEBUG StatusLogger Class name: [org.apache.log4j.RollingFileAppender]
DEBUG StatusLogger Parsing layout of class: "org.apache.log4j.PatternLayout"
DEBUG StatusLogger PluginManager 'Converter' found 47 plugins
TRACE StatusLogger New file '${catalina.base}/etl.log' created = true
DEBUG StatusLogger Returning file creation time for C:\dev\apache-tomcat-8.5.50\bin\${catalina.base}\etl.log
DEBUG StatusLogger Starting RollingFileManager ${catalina.base}/etl.log
...

The log file is being created in a folder named "${catalina.base}", in whatever directory I'm in when I start tomcat. How do I get the log4j1 bridge to recognize the value of the system property rather than using the literal property name?

What am I doing wrong? TIA for any advice anyone can provide.


Solution

  • Unless I am mistaken, this is a bug in the support of Log4j 1.x XML configurations. Support for Log4j 1.x variable substitutions was introduced in this commit (it works only if you use org.apache.log4j.config.Log4j1ConfigurationFactory, which is not the default) for the properties format, but an equivalent change for the XML format is missing. You should report it.

    In the meantime you can use ${sys:catalina.base} as a workaround (basically the Log4j 1.x bridge supports Log4j 2.x lookups, instead of simple system property substitution).

    Edit: The Log4j 1.x bridge has three configuration factories:

    • Log4j1ConfigurationFactory supports only *.properties files and has been using property substitution since the commit mentioned above (2016),
    • support for property substitution in the PropertiesConfigurationFactory was added in LOG4J2-2951 as mentioned by Paul in the comments,
    • lack of support for property substitution in the XmlConfigurationFactory has been reported by Paul as LOG4J2-3328.