Search code examples
loggingweb-applicationslog4jlog4j2slf4j

log4j stops logging (some) log message


We are running a fairly typical but "legacy" webapp using log4j under slf4j and Spring 5.3.18. (I'll update with versions of log4j/slf4j) We use an external log4j config file specified on Tomcat startup as -Dlog4j.configurationFile=our-log4j2.xml. This worked fine for several years.

A while back we noticed that sometimes our logs weren't showing up when we deployed a new version of our application. At first, we thought it was all logs. For some reason, a rebuild/redeploy through our Jenkins pipeline seemed to fix it every time. (we now have a theory that the build is doing something odd and sometimes works, sometimes not. more later) After time, we realize we DO get SOME logs presumably through the ROOT logger but not all. I'll forego the jsonfile config for now.

<Root level="INFO">
    <AppenderRef ref="jsonfile"/>
</Root>

Lately, the problem seems to be progressively more problematic and a single rebuild is often not sufficient to get it working. About the only runtime clue is the following. After a successful log4j initialization sequence (inferred from the logs to catalina.out), we get the ubiquitous:

log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory)

This example shows ibatis but sometimes it is Spring related classes and sometimes others.

As you might suspect, we DO NOT get this in the logs when logging works as expected.

I'm happy to provide supporting information as people ask but am hesitant to do so initially as this does not seem like the typical "problem with missing/wrong config" issue since sometimes a simple rebuild/redeploy with everything exactly the same will "fix" it.

Some possibly related context information:

  • Again, Maven build via Jenkins deployed to Tomcat 9.
  • Servers are linux / AWS EC2.

We are really scratching our heads on this one. Any help/ideas is appreciated.

[Update 3/2] My reply to Piotr's comment is either wrong or misleading. We have had the following in our POM the entire time. Based on his initial suggestion, including this dependency is why it works (sometimes):

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-1.2-api</artifactId>
        </dependency>

When logging works, here is the content of our WEB-INF/lib:

log4j-api-2.17.2.jar  
log4j-core-2.17.2.jar
log4j-1.2-api-2.17.2.jar  <<<
slf4j-api-1.7.35.jar
slf4j-reload4j-1.7.35.jar

Any time we remove log4j-1.2-api-2.17.2.jar, it does not work. Unfortunately, it still sometimes does not work (including getting the warning) even when that dependency/jar is present :(


Solution

  • Reload4j is a fork of the original Log4j 1.2 project.

    Since you have slf4j-reload4j on your classpath all logging performed using SLF4J is either sent to reload4j or log4j-1.2-api (they use the same class names).

    You need to:

    • redirect SLF4J to the Log4j2 API by removing slf4j-reload4j adding log4j-slf4j-impl as runtime dependency,
    • most libraries (especially these days) are not coded directly against Log4j 1.x but use one of the facades: Apache Commons Logging, SLF4J, JBoss Logging, Log4j2 API... You probably can remove log4j-1.2-api, reload4j or any other Log4j 1.x replacements from your classpath.