I found one more issue.

When webapps load I got the error "*ERROR StatusLogger No configuration found for context '...'*."  that appears to indicate that those apps aren't actually loading the Tomcat log4j2-tomcat.xml configuration.

The instructions I located are to ALSO include log4j-web-2.*.jar in the Maven build of the webapps and in the log4j2\lib folder.

Unfortunately, that still causes the error to show up on webapp load, and the configuration to fail to be used by the webapps.

What is most frustrating is that at this point Tomcat is indeed loading the log4j2-tomcat.xml as I see the files and folders specified in the log4j2-tomcat.xml are indeed getting created, even if none of the webapp logging is happening, only server logging is.

B.

On 3/11/2025 10:50 AM, Bruno Melloni wrote:
Thanks, excellent set of links and information!

 * [2] is almost identical to what I "used to use" for Tomcat 8 and 10
   log4j 2.x logging (the only real difference is the folder names I
   chose).   I am not sure when, but at some point this solution
   stopped working with Tomcat 10 (it still works with Tomcat 8).
 * After a lot of troubleshooting I discovered that for Tomcat 10
   (using just the apps included with the distribution) I had to also
   add
-Djava.uytil.logging.manager=org.apache.logging.log4j.jul.LoggingManager
   and
-Dlog4j.configurationFile=file:%CATALINA_HOME%\log4j\log4j2-tomcat.xml
   to setenv.bat.
 * I also had to replace the "handlers" variable to only include
   org.apache.logging.log4j.jul.LogManager in logging.properties.
   Simply deleting logging.properties and/or tomcat-juli.jar does not
   work as now Tomcat requires those to be present, as the log4j pieces
   only allow for those tomcat-juli libraries to forward to the log4j
   libraries.

The only remaining issue is that apparently _log4j 2.20.0 LogManager does not seem to implement the java.util.logging.Handler interface_.  I am not positive yet, but this does not appear to be a serious issue.   I did notice that it causes an exception when you run shutdown.bat, and once every time a webapp (any webapp) is loaded onto Tomcat.

So, the solution these days seems to be a little more complex than the old solution of simply implementing [2].


Still, your various links are an excellent resource to continue troubleshooting and hopefully find a complete solution.

B.


On 3/10/2025 5:58 PM, Piotr P. Karwasz wrote:
Hi Bruno,

On 10.03.2025 18:01, Bruno Melloni wrote:
I am wondering because after easily a decade of using log4j with Tomcat... it is now virtually impossible to find instructions (_that actually work_) for how to configure Tomcat 10 to use *Apache Log4j* as its default logger. Since both are Tomcat projects, the only explanation I could come up with is that maybe Apache Log4j is considered a dead project by Apache even if not announced as so.

The rumors about Apache Log4j death are greatly exaggerated. The easiest way to verify the status of an Apache project is to read the quarterly reports of the overseeing PMC[1].

There are two reasons, why Log4j and Tomcat are not more closely integrated:

1. Apache PMCs are very independent and there is no Foundation-wide rule that obliges a PMC to prefer dependencies produced by other Apache projects.

2. There are not many user requests to more closely integrate the two projects.

[1] https://whimsy.apache.org/board/minutes/Logging_Services.html


If you are looking for instructions on how to replace Tomcat's default logging backend with Log4j Core, there is a dedicated section[2] in our new Integrating Log4j Core with Jakarta EE Guide[3]

[2] https://logging.apache.org/log4j/2.x/jakarta.html#replace-tomcat

[3] https://logging.apache.org/log4j/2.x/jakarta.html


The above instructions only redirect server logs to Log4j Core, while web applications will use whatever logging backend they bundle. If you are looking for a tighter integration between server logs and webapp logs, I wrote a couple of Log4j Core Plugins and Tomcat Components[4] to better integrate the two. Basically what you need to do is:

1. Use a special web application classloader[5] that delegates the loading of `org.apache.logging.log4j.*` classes to the parent classloader (the standard classloader only delegates the loading of `jakarta.*` and `org.apache.tomcat.*` classes to the parent).

2. Use some strategy to distinguish between the logs sent by different web applications. There are basically two strategies available:

    * You can split your loggers in logger contexts using an appropriate Log4j Core context selector[6]. This way each web application can have its own configuration file (but doesn't need to). The naming strategy for logging configuration files is inspired by Tomcat's context configuration naming convention.

    * You can use a single logger context and use a Log4j Core context data provider[7] to enrich each message with the name of the context that generated it. This is probably the best strategy if you forward your logs to ElasticSearch or similar.

TL;DR: There is a short guide for my extensions at [8].

[4] https://oss.copernik.eu/tomcat/3.x/

[5] https://oss.copernik.eu/tomcat/3.x/components/tomcat-log4j#classloaders

[6] https://oss.copernik.eu/tomcat/3.x/components/log4j-tomcat#TomcatContextSelector

[7] https://oss.copernik.eu/tomcat/3.x/components/log4j-tomcat#TomcatContextDataProvider

[8] https://oss.copernik.eu/tomcat/3.x/guide

And even though I think I figured out a configuration that appears to work, when I call shutdown.bat (and in a few other scenarios) I get the error:

*class org.apache.logging.log4j.jul.LogManager cannot be cast to class java.util.logging.Handler (org.apache.logging.log4j.jul.LogManager is in unnamed module of loader 'app'; java.util.logging.Handler is in module java.logging of loader 'bootstrap')*

I am using Java 17, Tomcat 10.1.7 and log4j 2.20.0.

You are probably trying to use `o.a.l.l.jul.LogManager` in the `logging.properties` configuration file. To replace the default implementation of `java.util.logging.LogManager` you need to add:

LOGGING_MANAGER="org.apache.logging.log4j.jul.LogManager"

to your `setenv.sh` file. See the documentation on Log4j's website[9].


As alternative you can keep the default `o.a.juli.ClassLoaderLogManager` and use a single `org.apache.logging.log4j.jul.Log4jBridgeHandler` in your `logging.properties` file. This method introduces a considerable overhead to logging, so you should also set the `propagateLevels` property to `true` to mitigate it. See [10] for more details.

[9] https://logging.apache.org/log4j/2.x/log4j-jul.html#bridge-logmanager

[10] https://logging.apache.org/log4j/2.x/log4j-jul.html#bridge-handler


Piotr


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to