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