You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Rainer Jung <ra...@kippdata.de> on 2016/10/25 13:17:55 UTC
TC 8.5 and Log4J2 via Juli: Wrong location info
Hi everyone,
when using TC 8.5 with the Log4J2 jul bridge the location info in the
Log4J output points to the juli class DirectJDKLog instead of the Tomcat
class with the juli log call. Only the category/logger name is correct:
%c: org.apache.catalina.core.StandardServer (Example, correct)
%C: org.apache.juli.logging.DirectJDKLog
%l: org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
%M: log
%F: DirectJDKLog.java
%L: 179
The jul bridge does not try to fully populate al possible location info,
but instead only the category name. Log4J then later gets the log
location from the stack frame that calls the jul bridge which always
gives org.apache.juli.logging.DirectJDKLog.
It seems we either need to directly call the jul bridge without an
intermediate logging impl class, or the Log4J2 jul bridge must be made
more complex.
Any opinion? Ideas?
I know that the location info is expensive to get, but failing to
support the correct location info is IMHO bad. The old adapter solution
supported correct location info in log4j.
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Mark Thomas <ma...@apache.org>.
On 17/04/17 13:41, Rainer Jung wrote:
> Am 17.04.2017 um 11:49 schrieb R�my Maucherat:
>> 2017-04-15 23:32 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>
>>> Coming back to this.
>>>
>>> Reminder:
>>>
>>> - in TC 8.5 we removed explicit support for Log4J(2)
>>>
>>> - we direct users at the Log4J2 JUL bridge
>>>
>>> - the Log4J2 JUL bridge works by adding the additional Log4J2 jar
>>> files to
>>> the CLASSPATH and setting LOGGING_MANAGER to
>>> -Djava.util.logging.manager=or
>>> g.apache.logging.log4j.jul.LogManager
>>>
>>> Now there's a problem: the log4j2 implementation of retrieving location
>>> info (e.g. %C, %l, %F, %L) from the stack isn't aware of our juli
>>> sitting
>>> between the real jul classes and log4J2 and so always results in
>>> org.apache.juli.logging.DirectJDKLog as location of the log event
>>> instead
>>> of the real class containing the log statement.
>>>
>>> Of course location info patterns are not recommended for performance
>>> reasons, nevertheless I think they should work correctly for debugging
>>> purposes.
>>>
>>> One suggested solution was:
>>>
>>> - add a org.apache.juli.logging.Log impl that delegates to Log4J2
>>> (instead
>>> of the JUL bridge)
>>>
>>> and
>>>
>>> - add a Log4jLogEventFactory that additionally skips our DirectJDKLog
>>> when
>>> looking for the location info in the stack.
>>>
>>> I implemented this. See the patch for 8.5 at
>>>
>>> http://home.apache.org/~rjung/patches/tc8.5.x-juli-log4j2.patch
>>>
>>> The way I did it, is adding back a tomcat-juli-adapters.jar, which
>>> contains the above two classes. Adding this instead of the Log4J2 JUL
>>> bridge to the CLASSPATH (plus the Log4J2 api and core jars, but no
>>> changes
>>> to LOGGING_MANAGER) result in Log4J2 being used and logging with correct
>>> location info.
>>>
>>> Would that make a useful addition for TC 8.5 (and 9)?
>>>
>>> Ok, so the dependency from extras to log4j is removed just to be added
>> back 5 minutes later as a real dependency. Interesting !
>> Personally, I'm probably going to vote "no".
>
> The idea here is not to remove some dependency but to fix the "wrong
> location info" problem/bug.
>
> Or do you see a new dependency creeping in here? The patch does
> introduce a compile time dependency to log4j but not a runtime
> dependency unless you are using the optional adapters jar (to fix the
> location info bug).
>
> I still do not see a better way to fix the problem.
It is a pity it looks like we'll have to re-introduce the adapter
concept to support log4j2 directly but I don't see a way around it.
Mark
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 17.04.2017 um 11:49 schrieb R�my Maucherat:
> 2017-04-15 23:32 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>
>> Coming back to this.
>>
>> Reminder:
>>
>> - in TC 8.5 we removed explicit support for Log4J(2)
>>
>> - we direct users at the Log4J2 JUL bridge
>>
>> - the Log4J2 JUL bridge works by adding the additional Log4J2 jar files to
>> the CLASSPATH and setting LOGGING_MANAGER to -Djava.util.logging.manager=or
>> g.apache.logging.log4j.jul.LogManager
>>
>> Now there's a problem: the log4j2 implementation of retrieving location
>> info (e.g. %C, %l, %F, %L) from the stack isn't aware of our juli sitting
>> between the real jul classes and log4J2 and so always results in
>> org.apache.juli.logging.DirectJDKLog as location of the log event instead
>> of the real class containing the log statement.
>>
>> Of course location info patterns are not recommended for performance
>> reasons, nevertheless I think they should work correctly for debugging
>> purposes.
>>
>> One suggested solution was:
>>
>> - add a org.apache.juli.logging.Log impl that delegates to Log4J2 (instead
>> of the JUL bridge)
>>
>> and
>>
>> - add a Log4jLogEventFactory that additionally skips our DirectJDKLog when
>> looking for the location info in the stack.
>>
>> I implemented this. See the patch for 8.5 at
>>
>> http://home.apache.org/~rjung/patches/tc8.5.x-juli-log4j2.patch
>>
>> The way I did it, is adding back a tomcat-juli-adapters.jar, which
>> contains the above two classes. Adding this instead of the Log4J2 JUL
>> bridge to the CLASSPATH (plus the Log4J2 api and core jars, but no changes
>> to LOGGING_MANAGER) result in Log4J2 being used and logging with correct
>> location info.
>>
>> Would that make a useful addition for TC 8.5 (and 9)?
>>
>> Ok, so the dependency from extras to log4j is removed just to be added
> back 5 minutes later as a real dependency. Interesting !
> Personally, I'm probably going to vote "no".
The idea here is not to remove some dependency but to fix the "wrong
location info" problem/bug.
Or do you see a new dependency creeping in here? The patch does
introduce a compile time dependency to log4j but not a runtime
dependency unless you are using the optional adapters jar (to fix the
location info bug).
I still do not see a better way to fix the problem.
Or maybe I misunderstood you.
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rémy Maucherat <re...@apache.org>.
2017-04-15 23:32 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Coming back to this.
>
> Reminder:
>
> - in TC 8.5 we removed explicit support for Log4J(2)
>
> - we direct users at the Log4J2 JUL bridge
>
> - the Log4J2 JUL bridge works by adding the additional Log4J2 jar files to
> the CLASSPATH and setting LOGGING_MANAGER to -Djava.util.logging.manager=or
> g.apache.logging.log4j.jul.LogManager
>
> Now there's a problem: the log4j2 implementation of retrieving location
> info (e.g. %C, %l, %F, %L) from the stack isn't aware of our juli sitting
> between the real jul classes and log4J2 and so always results in
> org.apache.juli.logging.DirectJDKLog as location of the log event instead
> of the real class containing the log statement.
>
> Of course location info patterns are not recommended for performance
> reasons, nevertheless I think they should work correctly for debugging
> purposes.
>
> One suggested solution was:
>
> - add a org.apache.juli.logging.Log impl that delegates to Log4J2 (instead
> of the JUL bridge)
>
> and
>
> - add a Log4jLogEventFactory that additionally skips our DirectJDKLog when
> looking for the location info in the stack.
>
> I implemented this. See the patch for 8.5 at
>
> http://home.apache.org/~rjung/patches/tc8.5.x-juli-log4j2.patch
>
> The way I did it, is adding back a tomcat-juli-adapters.jar, which
> contains the above two classes. Adding this instead of the Log4J2 JUL
> bridge to the CLASSPATH (plus the Log4J2 api and core jars, but no changes
> to LOGGING_MANAGER) result in Log4J2 being used and logging with correct
> location info.
>
> Would that make a useful addition for TC 8.5 (and 9)?
>
> Ok, so the dependency from extras to log4j is removed just to be added
back 5 minutes later as a real dependency. Interesting !
Personally, I'm probably going to vote "no".
Rémy
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Coming back to this.
Reminder:
- in TC 8.5 we removed explicit support for Log4J(2)
- we direct users at the Log4J2 JUL bridge
- the Log4J2 JUL bridge works by adding the additional Log4J2 jar files
to the CLASSPATH and setting LOGGING_MANAGER to
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
Now there's a problem: the log4j2 implementation of retrieving location
info (e.g. %C, %l, %F, %L) from the stack isn't aware of our juli
sitting between the real jul classes and log4J2 and so always results in
org.apache.juli.logging.DirectJDKLog as location of the log event
instead of the real class containing the log statement.
Of course location info patterns are not recommended for performance
reasons, nevertheless I think they should work correctly for debugging
purposes.
One suggested solution was:
- add a org.apache.juli.logging.Log impl that delegates to Log4J2
(instead of the JUL bridge)
and
- add a Log4jLogEventFactory that additionally skips our DirectJDKLog
when looking for the location info in the stack.
I implemented this. See the patch for 8.5 at
http://home.apache.org/~rjung/patches/tc8.5.x-juli-log4j2.patch
The way I did it, is adding back a tomcat-juli-adapters.jar, which
contains the above two classes. Adding this instead of the Log4J2 JUL
bridge to the CLASSPATH (plus the Log4J2 api and core jars, but no
changes to LOGGING_MANAGER) result in Log4J2 being used and logging with
correct location info.
Would that make a useful addition for TC 8.5 (and 9)?
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rémy Maucherat <re...@apache.org>.
2016-10-26 20:04 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Am 26.10.2016 um 16:02 schrieb Rémy Maucherat:
>
>> 2016-10-26 15:32 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
>>
>> If I got the original issue right, it is only about allowing a user to
>>> replace the default (JULi) so should be acceptable, no?
>>>
>>> Right, but once you place your logging framework in the main CL, you
>>> could
>>>
>> run into issues. The default is indeed not affected.
>>
>
> Understood, there's lots of ways to do it wrong and disturb a webapp
> provided Log4J2 instance when adding one to the main CL. Nevertheless I
> like the advanced features of the fully fledged log framework and Log4J2
> got much better allowing to do it right.
>
> +1
Rémy
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 26.10.2016 um 16:02 schrieb R�my Maucherat:
> 2016-10-26 15:32 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
>
>> If I got the original issue right, it is only about allowing a user to
>> replace the default (JULi) so should be acceptable, no?
>>
>> Right, but once you place your logging framework in the main CL, you could
> run into issues. The default is indeed not affected.
Understood, there's lots of ways to do it wrong and disturb a webapp
provided Log4J2 instance when adding one to the main CL. Nevertheless I
like the advanced features of the fully fledged log framework and Log4J2
got much better allowing to do it right.
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Romain Manni-Bucau <rm...@gmail.com>.
2016-10-26 16:02 GMT+02:00 Rémy Maucherat <re...@apache.org>:
> 2016-10-26 15:32 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
>
> > If I got the original issue right, it is only about allowing a user to
> > replace the default (JULi) so should be acceptable, no?
> >
> > Right, but once you place your logging framework in the main CL, you
> could
> run into issues. The default is indeed not affected.
>
>
You can see it both way "**** i"m affected" or "yeah, I inherit from the
ops config". That why I think it is good to let it be "up to the user".
> Rémy
>
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rémy Maucherat <re...@apache.org>.
2016-10-26 15:32 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
> If I got the original issue right, it is only about allowing a user to
> replace the default (JULi) so should be acceptable, no?
>
> Right, but once you place your logging framework in the main CL, you could
run into issues. The default is indeed not affected.
Rémy
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 26.10.2016 um 15:32 schrieb Romain Manni-Bucau:
> 2016-10-26 11:50 GMT+02:00 R�my Maucherat <re...@apache.org>:
>
>> 2016-10-26 11:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>
>>> Note that for the jul bridge to work, the Log4J2 jar files have to be put
>>> onto the CLASSPATH (otherwise the Log4J2 jul LogManager can't be used)
>> and
>>> so the resource pointing to the custom LogEventFactory must sit there as
>>> well.
>>>
>>> But it seems one of my early tests was wrong. The custom factory is *not*
>>> being loaded by a webapp local Log4J2 instance. At least not with the
>> setup
>>> I originally described.
>>>
>>> So putting the factory and the log4j2.component.properties file into the
>>> tomcat-juli.jar should be transparent (to webapps and also the setups
>> which
>>> do not use Log4J2 at all) and would be one solution to the original
>> problem
>>> of wrong location info. I still need to test behavior if webapps use juli
>>> as well.
>>>
>>> Whether we also want to directly support Log4J2 with an SPI provided Log
>>> implementation that delegates to Log4J2 is still open. Personally I find
>> it
>>> somewhat cleaner to point to the Log4J standard way (adding the jul
>> bridge
>>> and other log4j jar files as well as the LogManager system property)
>>> instead of needing to activate/add a separate TC jar file containing the
>>> new Log impl and SPI meta data. It seems the only way to activate the log
>>> impl via SPI is adding the containing jar to the class loader search path
>>> (likely CLASSPATH).
>>>
>>> One of the problems of using a standard logging framework was class
>> conflicts (the webapps can see a shared log4j, they can try to override it,
>> but it could cause issues).
>>
>
> If I got the original issue right, it is only about allowing a user to
> replace the default (JULi) so should be acceptable, no?
Yes, the original problem is, that we removed juli-adapters and claim
that using Log4J2 as an alternative log framework for Tomcat now works
out-of-the box using the jul support in Log4J2.
See https://bz.apache.org/bugzilla/show_bug.cgi?id=58588 and the
corresponding changelog entry for 8.5.4:
58588: Remove the JULI extras package from the distribution. It was
only useful for switching Tomcat's internal logging to log4j 1.2.x and
that version of log4j is no longer supported. No additional Tomcat code
is required if switching Tomcat's internal logging to log via log4j 2.x.
(markt)
When actually using this I noticed, that the location info in the log
statements is wrong and can't be fixed with TC or Log4Js out-of-the-box
features. Due to your hints, we now know how to fix it by adding a
LogEventFactory and making it available to Log4J2 using a properties
files as a class loaded ressource.
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Romain Manni-Bucau <rm...@gmail.com>.
2016-10-26 11:50 GMT+02:00 Rémy Maucherat <re...@apache.org>:
> 2016-10-26 11:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>
> > Note that for the jul bridge to work, the Log4J2 jar files have to be put
> > onto the CLASSPATH (otherwise the Log4J2 jul LogManager can't be used)
> and
> > so the resource pointing to the custom LogEventFactory must sit there as
> > well.
> >
> > But it seems one of my early tests was wrong. The custom factory is *not*
> > being loaded by a webapp local Log4J2 instance. At least not with the
> setup
> > I originally described.
> >
> > So putting the factory and the log4j2.component.properties file into the
> > tomcat-juli.jar should be transparent (to webapps and also the setups
> which
> > do not use Log4J2 at all) and would be one solution to the original
> problem
> > of wrong location info. I still need to test behavior if webapps use juli
> > as well.
> >
> > Whether we also want to directly support Log4J2 with an SPI provided Log
> > implementation that delegates to Log4J2 is still open. Personally I find
> it
> > somewhat cleaner to point to the Log4J standard way (adding the jul
> bridge
> > and other log4j jar files as well as the LogManager system property)
> > instead of needing to activate/add a separate TC jar file containing the
> > new Log impl and SPI meta data. It seems the only way to activate the log
> > impl via SPI is adding the containing jar to the class loader search path
> > (likely CLASSPATH).
> >
> > One of the problems of using a standard logging framework was class
> conflicts (the webapps can see a shared log4j, they can try to override it,
> but it could cause issues).
>
If I got the original issue right, it is only about allowing a user to
replace the default (JULi) so should be acceptable, no?
>
> Rémy
>
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rémy Maucherat <re...@apache.org>.
2016-10-26 11:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Note that for the jul bridge to work, the Log4J2 jar files have to be put
> onto the CLASSPATH (otherwise the Log4J2 jul LogManager can't be used) and
> so the resource pointing to the custom LogEventFactory must sit there as
> well.
>
> But it seems one of my early tests was wrong. The custom factory is *not*
> being loaded by a webapp local Log4J2 instance. At least not with the setup
> I originally described.
>
> So putting the factory and the log4j2.component.properties file into the
> tomcat-juli.jar should be transparent (to webapps and also the setups which
> do not use Log4J2 at all) and would be one solution to the original problem
> of wrong location info. I still need to test behavior if webapps use juli
> as well.
>
> Whether we also want to directly support Log4J2 with an SPI provided Log
> implementation that delegates to Log4J2 is still open. Personally I find it
> somewhat cleaner to point to the Log4J standard way (adding the jul bridge
> and other log4j jar files as well as the LogManager system property)
> instead of needing to activate/add a separate TC jar file containing the
> new Log impl and SPI meta data. It seems the only way to activate the log
> impl via SPI is adding the containing jar to the class loader search path
> (likely CLASSPATH).
>
> One of the problems of using a standard logging framework was class
conflicts (the webapps can see a shared log4j, they can try to override it,
but it could cause issues).
Rémy
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 26.10.2016 um 08:33 schrieb Romain Manni-Bucau:
> 2016-10-26 8:26 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>
>> Am 25.10.2016 um 22:40 schrieb Romain Manni-Bucau:
>>
>>> 2016-10-25 22:35 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>>
>>> Am 25.10.2016 um 17:07 schrieb Romain Manni-Bucau:
>>>> I'm not sure though, how dangerous this is due to possible effects on
>>>> Log4J2 in some webapp. IMHO the alternative LogEvent and LogEventFactory
>>>> impl must be made available for Tomcat use already in the CLASSPATH. The
>>>> server loader could already be too late. That means it is also visible to
>>>> any webapp. And activating it is done either via a system property, or a
>>>> resource named log4j2.component.properties which contains the property
>>>>
>>>> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>>>>
>>>> Again this resource IMHO must reside in the CLASSPATH. So both ways of
>>>> activating the alternative LogEvent impl also activate it for any Log4J2
>>>> in
>>>> any webapp.
>>>>
>>>>
>>>> True or not, nothing prevents to run it in a logger classloader to
>>> isolate
>>> from webapp. That said if you want tomcat to log with log4j2 you likely
>>> also want the webapps to do the same IMO. Also tomcat has a classloader
>>> context selector so config can be per webapp or at least hook is there for
>>> that.
>>>
>>
>> I was more concerned about a webapp that does not use juli, but uses
>> Log4J2 directly (or via SLF4J etc.). We should not disturb the behavior of
>> such a webapp by our Tomcat log setup.
>>
>>
> Yes Tomcat is not yet able to filter resources by classloader (Loader could
> get a config for that with defaults, we do it in tomee for slf4j and
> several specs for instance)
Note that for the jul bridge to work, the Log4J2 jar files have to be
put onto the CLASSPATH (otherwise the Log4J2 jul LogManager can't be
used) and so the resource pointing to the custom LogEventFactory must
sit there as well.
But it seems one of my early tests was wrong. The custom factory is
*not* being loaded by a webapp local Log4J2 instance. At least not with
the setup I originally described.
So putting the factory and the log4j2.component.properties file into the
tomcat-juli.jar should be transparent (to webapps and also the setups
which do not use Log4J2 at all) and would be one solution to the
original problem of wrong location info. I still need to test behavior
if webapps use juli as well.
Whether we also want to directly support Log4J2 with an SPI provided Log
implementation that delegates to Log4J2 is still open. Personally I find
it somewhat cleaner to point to the Log4J standard way (adding the jul
bridge and other log4j jar files as well as the LogManager system
property) instead of needing to activate/add a separate TC jar file
containing the new Log impl and SPI meta data. It seems the only way to
activate the log impl via SPI is adding the containing jar to the class
loader search path (likely CLASSPATH).
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Romain Manni-Bucau <rm...@gmail.com>.
2016-10-26 8:26 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Am 25.10.2016 um 22:40 schrieb Romain Manni-Bucau:
>
>> 2016-10-25 22:35 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>
>> Am 25.10.2016 um 17:07 schrieb Romain Manni-Bucau:
>>>
>>> This has the issue but the fix is easy and 100% belonging to the Log impl
>>>> jar:
>>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>>> /microwave-core/src/main/java/org/apache/microwave/logging/
>>>> log4j2/MicrowaveLogEventFactory.java
>>>> and
>>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>>> /microwave-core/src/main/resources/log4j2.component.properties
>>>>
>>>>
>>>> Romain Manni-Bucau
>>>> @rmannibucau <https://twitter.com/rmannibucau> | Blog
>>>> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
>>>> <http://rmannibucau.wordpress.com> | Github <
>>>> https://github.com/rmannibucau> |
>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
>>>> <http://www.tomitribe.com> | JavaEE Factory
>>>> <https://javaeefactory-rmannibucau.rhcloud.com>
>>>>
>>>> 2016-10-25 16:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>>>
>>>> Am 25.10.2016 um 15:33 schrieb Romain Manni-Bucau:
>>>>
>>>>>
>>>>> Hi guys,
>>>>>
>>>>>>
>>>>>> since now tomcat has Log API as a SPI doing 2 is easy (
>>>>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>>>>> /microwave-core/src/main/java/org/apache/microwave/logging/
>>>>>> tomcat/Log4j2Log.java)
>>>>>> and
>>>>>> just a drop-in jar setup so not sure it needs to be in tomcat default
>>>>>> delivery.
>>>>>>
>>>>>>
>>>>>> I tried to plug in Log4j2Log.java using SPI. It gets used, but it
>>>>> doesn't
>>>>> fix the problem. Now the location info points to Log4j2Log instead of
>>>>> DirectJDKLog. The Problem of one indirection layer to much above Log4Js
>>>>> has't changed.
>>>>>
>>>>> I think the jul log bridge removes one frame, which is the jul loger,
>>>>> ending up taking the DirectJDKLog which vcalls the jul logger as its
>>>>> location. Using your approach does no longer use jul, so log4j2 doesn't
>>>>> re
>>>>> move a frame and again takes the wrong class Log4j2Log as its location
>>>>> info.
>>>>>
>>>>> I think delegating is not enough, you actually need to implement the
>>>>> target API or extend a target implementation.
>>>>>
>>>>> Did you check the location info using the SPI approach?
>>>>>
>>>>> Regards,
>>>>>
>>>>> Rainer
>>>>>
>>>>>
>>>> Thanks for that hint. Actually I hadn't noticed this trick to overwrite
>>> the getSource() logic.
>>>
>>> I'm not sure though, how dangerous this is due to possible effects on
>>> Log4J2 in some webapp. IMHO the alternative LogEvent and LogEventFactory
>>> impl must be made available for Tomcat use already in the CLASSPATH. The
>>> server loader could already be too late. That means it is also visible to
>>> any webapp. And activating it is done either via a system property, or a
>>> resource named log4j2.component.properties which contains the property
>>>
>>> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>>>
>>> Again this resource IMHO must reside in the CLASSPATH. So both ways of
>>> activating the alternative LogEvent impl also activate it for any Log4J2
>>> in
>>> any webapp.
>>>
>>>
>>> True or not, nothing prevents to run it in a logger classloader to
>> isolate
>> from webapp. That said if you want tomcat to log with log4j2 you likely
>> also want the webapps to do the same IMO. Also tomcat has a classloader
>> context selector so config can be per webapp or at least hook is there for
>> that.
>>
>
> I was more concerned about a webapp that does not use juli, but uses
> Log4J2 directly (or via SLF4J etc.). We should not disturb the behavior of
> such a webapp by our Tomcat log setup.
>
>
Yes Tomcat is not yet able to filter resources by classloader (Loader could
get a config for that with defaults, we do it in tomee for slf4j and
several specs for instance)
> Using a specific class loader for loading TC logging resources/config
> might work (although it will have the usual problem, that logging isn't set
> up correctly before the loader is in place). Setting it up as I described
> it might have side effects on deployed webapps due to delegation rules.
> I'll try to find time to check this.
>
>
Should be fine, worse case the constraint would be to do the
LogManager.getLogger lazily which is acceptable for bootstrap loggers (no
runtime performance constraint).
> Although the code of the LogEvent looks compatible with the standard one,
>>> this is only true as long as we consider Log4jLogEvent being the standard
>>> one. Unfortunately the Log4J2 class LoggerConfig can use
>>> DefaultLogEventFactory (which indeed uses Log4jLogEvent) but also
>>> ReusableLogEventFactory, which uses thread-local MutableLogEvent.
>>>
>>> So I'm not sure how safe this replacement is.
>>>
>>>
>>> the properties config enforces it. It can get more config love but think
>> it
>> already works not bad.
>>
>
> By "safe" I did not mean whether it will work in any case, but whether it
> can disturb deployed contexts.
>
> Sure, that was my point too: if the factory is context aware you can
delegate to the local LoggerConfig when not in tomcat common (and shared?)
classloader.
>
> For anyone who wants to experiment here's what I did:
>>>
>>> - create file log4j2.component.properties with the single line:
>>>
>>> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>>>
>>> - create class JuliLogEventFactory.java very similar to the one Romain
>>> created. I'll paste it inline further down.
>>>
>>> - Put the class and the properties file into some new jar
>>> (tomcat-juli.jar
>>> should also work)
>>>
>>> - Add the new jar and from Log4J2 log4j-api.jar, log4j-core.jar and
>>> log4j-jul.jar to the CLASSPATH
>>>
>>> - Add a Log4J2 config (I have added its location to CLASSPATH)
>>>
>>> - Set
>>>
>>> LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logg
>>> ing.log4j.jul.LogManager"
>>>
>>> As a result the logged location info now works although the jul bridge is
>>> being used. But as said above, I'm not so sure about dangers for webapp
>>> provided Log4J2. Note that not using the jul bridge by Romain's SPI idea
>>> still needs a very similar location info fix. So we can split the
>>> discussion about how to fix location info from the discussion whether we
>>> prefer the jul bridge or a tomcat provided Log4J2 logger via SPI.
>>>
>>> For the sake of completeness, here's the call stack we need to handle to
>>> find the location info when using the Log4J2 jul bridge:
>>>
>>> ...
>>> org.apache.logging.log4j.core.Logger.logMessage(Logger.java:147)
>>> org.apache.logging.log4j.spi.ExtendedLoggerWrapper.logMessag
>>> e(ExtendedLoggerWrapper.java:217)
>>> org.apache.logging.log4j.spi.AbstractLogger.logMessage(Abstr
>>> actLogger.java:1993)
>>> org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(Abs
>>> tractLogger.java:1852)
>>> org.apache.logging.log4j.jul.WrappedLogger.log(WrappedLogger.java:50)
>>> org.apache.logging.log4j.jul.ApiLogger.log(ApiLogger.java:112)
>>> org.apache.logging.log4j.jul.ApiLogger.logp(ApiLogger.java:132)
>>> org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
>>> org.apache.juli.logging.DirectJDKLog.info(DirectJDKLog.java:122)
>>> -> here comes the wanted location
>>> ...
>>>
>>
> Regards,
>
> Rainer
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 25.10.2016 um 22:40 schrieb Romain Manni-Bucau:
> 2016-10-25 22:35 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>
>> Am 25.10.2016 um 17:07 schrieb Romain Manni-Bucau:
>>
>>> This has the issue but the fix is easy and 100% belonging to the Log impl
>>> jar:
>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>> /microwave-core/src/main/java/org/apache/microwave/logging/
>>> log4j2/MicrowaveLogEventFactory.java
>>> and
>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>> /microwave-core/src/main/resources/log4j2.component.properties
>>>
>>>
>>> Romain Manni-Bucau
>>> @rmannibucau <https://twitter.com/rmannibucau> | Blog
>>> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
>>> <http://rmannibucau.wordpress.com> | Github <
>>> https://github.com/rmannibucau> |
>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
>>> <http://www.tomitribe.com> | JavaEE Factory
>>> <https://javaeefactory-rmannibucau.rhcloud.com>
>>>
>>> 2016-10-25 16:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>>
>>> Am 25.10.2016 um 15:33 schrieb Romain Manni-Bucau:
>>>>
>>>> Hi guys,
>>>>>
>>>>> since now tomcat has Log API as a SPI doing 2 is easy (
>>>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>>>> /microwave-core/src/main/java/org/apache/microwave/logging/
>>>>> tomcat/Log4j2Log.java)
>>>>> and
>>>>> just a drop-in jar setup so not sure it needs to be in tomcat default
>>>>> delivery.
>>>>>
>>>>>
>>>> I tried to plug in Log4j2Log.java using SPI. It gets used, but it doesn't
>>>> fix the problem. Now the location info points to Log4j2Log instead of
>>>> DirectJDKLog. The Problem of one indirection layer to much above Log4Js
>>>> has't changed.
>>>>
>>>> I think the jul log bridge removes one frame, which is the jul loger,
>>>> ending up taking the DirectJDKLog which vcalls the jul logger as its
>>>> location. Using your approach does no longer use jul, so log4j2 doesn't
>>>> re
>>>> move a frame and again takes the wrong class Log4j2Log as its location
>>>> info.
>>>>
>>>> I think delegating is not enough, you actually need to implement the
>>>> target API or extend a target implementation.
>>>>
>>>> Did you check the location info using the SPI approach?
>>>>
>>>> Regards,
>>>>
>>>> Rainer
>>>>
>>>
>> Thanks for that hint. Actually I hadn't noticed this trick to overwrite
>> the getSource() logic.
>>
>> I'm not sure though, how dangerous this is due to possible effects on
>> Log4J2 in some webapp. IMHO the alternative LogEvent and LogEventFactory
>> impl must be made available for Tomcat use already in the CLASSPATH. The
>> server loader could already be too late. That means it is also visible to
>> any webapp. And activating it is done either via a system property, or a
>> resource named log4j2.component.properties which contains the property
>>
>> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>>
>> Again this resource IMHO must reside in the CLASSPATH. So both ways of
>> activating the alternative LogEvent impl also activate it for any Log4J2 in
>> any webapp.
>>
>>
> True or not, nothing prevents to run it in a logger classloader to isolate
> from webapp. That said if you want tomcat to log with log4j2 you likely
> also want the webapps to do the same IMO. Also tomcat has a classloader
> context selector so config can be per webapp or at least hook is there for
> that.
I was more concerned about a webapp that does not use juli, but uses
Log4J2 directly (or via SLF4J etc.). We should not disturb the behavior
of such a webapp by our Tomcat log setup.
Using a specific class loader for loading TC logging resources/config
might work (although it will have the usual problem, that logging isn't
set up correctly before the loader is in place). Setting it up as I
described it might have side effects on deployed webapps due to
delegation rules. I'll try to find time to check this.
>> Although the code of the LogEvent looks compatible with the standard one,
>> this is only true as long as we consider Log4jLogEvent being the standard
>> one. Unfortunately the Log4J2 class LoggerConfig can use
>> DefaultLogEventFactory (which indeed uses Log4jLogEvent) but also
>> ReusableLogEventFactory, which uses thread-local MutableLogEvent.
>>
>> So I'm not sure how safe this replacement is.
>>
>>
> the properties config enforces it. It can get more config love but think it
> already works not bad.
By "safe" I did not mean whether it will work in any case, but whether
it can disturb deployed contexts.
>> For anyone who wants to experiment here's what I did:
>>
>> - create file log4j2.component.properties with the single line:
>>
>> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>>
>> - create class JuliLogEventFactory.java very similar to the one Romain
>> created. I'll paste it inline further down.
>>
>> - Put the class and the properties file into some new jar (tomcat-juli.jar
>> should also work)
>>
>> - Add the new jar and from Log4J2 log4j-api.jar, log4j-core.jar and
>> log4j-jul.jar to the CLASSPATH
>>
>> - Add a Log4J2 config (I have added its location to CLASSPATH)
>>
>> - Set
>>
>> LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logg
>> ing.log4j.jul.LogManager"
>>
>> As a result the logged location info now works although the jul bridge is
>> being used. But as said above, I'm not so sure about dangers for webapp
>> provided Log4J2. Note that not using the jul bridge by Romain's SPI idea
>> still needs a very similar location info fix. So we can split the
>> discussion about how to fix location info from the discussion whether we
>> prefer the jul bridge or a tomcat provided Log4J2 logger via SPI.
>>
>> For the sake of completeness, here's the call stack we need to handle to
>> find the location info when using the Log4J2 jul bridge:
>>
>> ...
>> org.apache.logging.log4j.core.Logger.logMessage(Logger.java:147)
>> org.apache.logging.log4j.spi.ExtendedLoggerWrapper.logMessag
>> e(ExtendedLoggerWrapper.java:217)
>> org.apache.logging.log4j.spi.AbstractLogger.logMessage(Abstr
>> actLogger.java:1993)
>> org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(Abs
>> tractLogger.java:1852)
>> org.apache.logging.log4j.jul.WrappedLogger.log(WrappedLogger.java:50)
>> org.apache.logging.log4j.jul.ApiLogger.log(ApiLogger.java:112)
>> org.apache.logging.log4j.jul.ApiLogger.logp(ApiLogger.java:132)
>> org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
>> org.apache.juli.logging.DirectJDKLog.info(DirectJDKLog.java:122)
>> -> here comes the wanted location
>> ...
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Romain Manni-Bucau <rm...@gmail.com>.
2016-10-25 22:35 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Am 25.10.2016 um 17:07 schrieb Romain Manni-Bucau:
>
>> This has the issue but the fix is easy and 100% belonging to the Log impl
>> jar:
>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>> /microwave-core/src/main/java/org/apache/microwave/logging/
>> log4j2/MicrowaveLogEventFactory.java
>> and
>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>> /microwave-core/src/main/resources/log4j2.component.properties
>>
>>
>> Romain Manni-Bucau
>> @rmannibucau <https://twitter.com/rmannibucau> | Blog
>> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
>> <http://rmannibucau.wordpress.com> | Github <
>> https://github.com/rmannibucau> |
>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
>> <http://www.tomitribe.com> | JavaEE Factory
>> <https://javaeefactory-rmannibucau.rhcloud.com>
>>
>> 2016-10-25 16:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>>
>> Am 25.10.2016 um 15:33 schrieb Romain Manni-Bucau:
>>>
>>> Hi guys,
>>>>
>>>> since now tomcat has Log API as a SPI doing 2 is easy (
>>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>>> /microwave-core/src/main/java/org/apache/microwave/logging/
>>>> tomcat/Log4j2Log.java)
>>>> and
>>>> just a drop-in jar setup so not sure it needs to be in tomcat default
>>>> delivery.
>>>>
>>>>
>>> I tried to plug in Log4j2Log.java using SPI. It gets used, but it doesn't
>>> fix the problem. Now the location info points to Log4j2Log instead of
>>> DirectJDKLog. The Problem of one indirection layer to much above Log4Js
>>> has't changed.
>>>
>>> I think the jul log bridge removes one frame, which is the jul loger,
>>> ending up taking the DirectJDKLog which vcalls the jul logger as its
>>> location. Using your approach does no longer use jul, so log4j2 doesn't
>>> re
>>> move a frame and again takes the wrong class Log4j2Log as its location
>>> info.
>>>
>>> I think delegating is not enough, you actually need to implement the
>>> target API or extend a target implementation.
>>>
>>> Did you check the location info using the SPI approach?
>>>
>>> Regards,
>>>
>>> Rainer
>>>
>>
> Thanks for that hint. Actually I hadn't noticed this trick to overwrite
> the getSource() logic.
>
> I'm not sure though, how dangerous this is due to possible effects on
> Log4J2 in some webapp. IMHO the alternative LogEvent and LogEventFactory
> impl must be made available for Tomcat use already in the CLASSPATH. The
> server loader could already be too late. That means it is also visible to
> any webapp. And activating it is done either via a system property, or a
> resource named log4j2.component.properties which contains the property
>
> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>
> Again this resource IMHO must reside in the CLASSPATH. So both ways of
> activating the alternative LogEvent impl also activate it for any Log4J2 in
> any webapp.
>
>
True or not, nothing prevents to run it in a logger classloader to isolate
from webapp. That said if you want tomcat to log with log4j2 you likely
also want the webapps to do the same IMO. Also tomcat has a classloader
context selector so config can be per webapp or at least hook is there for
that.
> Although the code of the LogEvent looks compatible with the standard one,
> this is only true as long as we consider Log4jLogEvent being the standard
> one. Unfortunately the Log4J2 class LoggerConfig can use
> DefaultLogEventFactory (which indeed uses Log4jLogEvent) but also
> ReusableLogEventFactory, which uses thread-local MutableLogEvent.
>
> So I'm not sure how safe this replacement is.
>
>
the properties config enforces it. It can get more config love but think it
already works not bad.
> For anyone who wants to experiment here's what I did:
>
> - create file log4j2.component.properties with the single line:
>
> Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
>
> - create class JuliLogEventFactory.java very similar to the one Romain
> created. I'll paste it inline further down.
>
> - Put the class and the properties file into some new jar (tomcat-juli.jar
> should also work)
>
> - Add the new jar and from Log4J2 log4j-api.jar, log4j-core.jar and
> log4j-jul.jar to the CLASSPATH
>
> - Add a Log4J2 config (I have added its location to CLASSPATH)
>
> - Set
>
> LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logg
> ing.log4j.jul.LogManager"
>
> As a result the logged location info now works although the jul bridge is
> being used. But as said above, I'm not so sure about dangers for webapp
> provided Log4J2. Note that not using the jul bridge by Romain's SPI idea
> still needs a very similar location info fix. So we can split the
> discussion about how to fix location info from the discussion whether we
> prefer the jul bridge or a tomcat provided Log4J2 logger via SPI.
>
> For the sake of completeness, here's the call stack we need to handle to
> find the location info when using the Log4J2 jul bridge:
>
> ...
> org.apache.logging.log4j.core.Logger.logMessage(Logger.java:147)
> org.apache.logging.log4j.spi.ExtendedLoggerWrapper.logMessag
> e(ExtendedLoggerWrapper.java:217)
> org.apache.logging.log4j.spi.AbstractLogger.logMessage(Abstr
> actLogger.java:1993)
> org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(Abs
> tractLogger.java:1852)
> org.apache.logging.log4j.jul.WrappedLogger.log(WrappedLogger.java:50)
> org.apache.logging.log4j.jul.ApiLogger.log(ApiLogger.java:112)
> org.apache.logging.log4j.jul.ApiLogger.logp(ApiLogger.java:132)
> org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
> org.apache.juli.logging.DirectJDKLog.info(DirectJDKLog.java:122)
> -> here comes the wanted location
> ...
>
> Regards,
>
> Rainer
>
> Class org.apache.juli.JuliLogEventFactory:
>
> /*
> * Licensed to the Apache Software Foundation (ASF) under one
> * or more contributor license agreements. See the NOTICE file
> * distributed with this work for additional information
> * regarding copyright ownership. The ASF licenses this file
> * to you under the Apache License, Version 2.0 (the
> * "License"); you may not use this file except in compliance
> * with the License. You may obtain a copy of the License at
> *
> * http://www.apache.org/licenses/LICENSE-2.0
> *
> * Unless required by applicable law or agreed to in writing,
> * software distributed under the License is distributed on an
> * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> * KIND, either express or implied. See the License for the
> * specific language governing permissions and limitations
> * under the License.
> */
> package org.apache.juli;
>
> import org.apache.logging.log4j.Level;
> import org.apache.logging.log4j.Marker;
> import org.apache.logging.log4j.core.LogEvent;
> import org.apache.logging.log4j.core.config.Property;
> import org.apache.logging.log4j.core.impl.DefaultLogEventFactory;
> import org.apache.logging.log4j.core.impl.Log4jLogEvent;
> import org.apache.logging.log4j.message.Message;
>
> import java.util.List;
>
> public class JuliLogEventFactory extends DefaultLogEventFactory {
> @Override
> public LogEvent createEvent(final String loggerName, final Marker
> marker, final String fqcn,
> final Level level, final Message data,
> final List<Property> properties,
> final Throwable t) {
> return new JuliLog4jLogEvent(loggerName, marker, fqcn, level,
> data, properties, t);
> }
>
> public static class JuliLog4jLogEvent extends Log4jLogEvent {
> private static final String juliLoggerName =
> "org.apache.juli.logging.DirectJDKLog";
>
> private StackTraceElement source = null;
>
> public JuliLog4jLogEvent(final String loggerName, final Marker
> marker, final String fqcn, final Level level,
> final Message data, final List<Property>
> properties, final Throwable t) {
> super(loggerName, marker, fqcn, level, data, properties, t);
> }
>
> /**
> * Returns the StackTraceElement for the caller. This will be the
> entry that occurs right
> * before the first occurrence of FQCN as a class name.
> * @return the StackTraceElement for the caller.
> */
> @Override
> public StackTraceElement getSource() {
> if (source != null) {
> return source;
> }
> String loggerFqcn = getLoggerFqcn();
> if (loggerFqcn == null || !isIncludeLocation()) {
> return null;
> }
> source = calcLocation(loggerFqcn);
> return source;
> }
>
> public static StackTraceElement calcLocation(final String
> fqcnOfLogger) {
> if (fqcnOfLogger == null) {
> return null;
> }
> // LOG4J2-1029 new Throwable().getStackTrace is faster than
> Thread.currentThread().getStackTrace().
> final StackTraceElement[] stackTrace = new
> Throwable().getStackTrace();
> StackTraceElement last = null;
> for (int i = stackTrace.length - 1; i > 0; i--) {
> final String className = stackTrace[i].getClassName();
> if (fqcnOfLogger.equals(className) ||
> juliLoggerName.equals(className)) {
> return last;
> }
> last = stackTrace[i];
> }
> return null;
>
> }
> }
> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 25.10.2016 um 17:07 schrieb Romain Manni-Bucau:
> This has the issue but the fix is easy and 100% belonging to the Log impl
> jar:
> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/java/org/apache/microwave/logging/log4j2/MicrowaveLogEventFactory.java
> and
> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/resources/log4j2.component.properties
>
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> | Blog
> <https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
> <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
> <http://www.tomitribe.com> | JavaEE Factory
> <https://javaeefactory-rmannibucau.rhcloud.com>
>
> 2016-10-25 16:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
>
>> Am 25.10.2016 um 15:33 schrieb Romain Manni-Bucau:
>>
>>> Hi guys,
>>>
>>> since now tomcat has Log API as a SPI doing 2 is easy (
>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>>> /microwave-core/src/main/java/org/apache/microwave/logging/
>>> tomcat/Log4j2Log.java)
>>> and
>>> just a drop-in jar setup so not sure it needs to be in tomcat default
>>> delivery.
>>>
>>
>> I tried to plug in Log4j2Log.java using SPI. It gets used, but it doesn't
>> fix the problem. Now the location info points to Log4j2Log instead of
>> DirectJDKLog. The Problem of one indirection layer to much above Log4Js
>> has't changed.
>>
>> I think the jul log bridge removes one frame, which is the jul loger,
>> ending up taking the DirectJDKLog which vcalls the jul logger as its
>> location. Using your approach does no longer use jul, so log4j2 doesn't re
>> move a frame and again takes the wrong class Log4j2Log as its location info.
>>
>> I think delegating is not enough, you actually need to implement the
>> target API or extend a target implementation.
>>
>> Did you check the location info using the SPI approach?
>>
>> Regards,
>>
>> Rainer
Thanks for that hint. Actually I hadn't noticed this trick to overwrite
the getSource() logic.
I'm not sure though, how dangerous this is due to possible effects on
Log4J2 in some webapp. IMHO the alternative LogEvent and LogEventFactory
impl must be made available for Tomcat use already in the CLASSPATH. The
server loader could already be too late. That means it is also visible
to any webapp. And activating it is done either via a system property,
or a resource named log4j2.component.properties which contains the property
Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
Again this resource IMHO must reside in the CLASSPATH. So both ways of
activating the alternative LogEvent impl also activate it for any Log4J2
in any webapp.
Although the code of the LogEvent looks compatible with the standard
one, this is only true as long as we consider Log4jLogEvent being the
standard one. Unfortunately the Log4J2 class LoggerConfig can use
DefaultLogEventFactory (which indeed uses Log4jLogEvent) but also
ReusableLogEventFactory, which uses thread-local MutableLogEvent.
So I'm not sure how safe this replacement is.
For anyone who wants to experiment here's what I did:
- create file log4j2.component.properties with the single line:
Log4jLogEventFactory=org.apache.juli.JuliLogEventFactory
- create class JuliLogEventFactory.java very similar to the one Romain
created. I'll paste it inline further down.
- Put the class and the properties file into some new jar
(tomcat-juli.jar should also work)
- Add the new jar and from Log4J2 log4j-api.jar, log4j-core.jar and
log4j-jul.jar to the CLASSPATH
- Add a Log4J2 config (I have added its location to CLASSPATH)
- Set
LOGGING_MANAGER="-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager"
As a result the logged location info now works although the jul bridge
is being used. But as said above, I'm not so sure about dangers for
webapp provided Log4J2. Note that not using the jul bridge by Romain's
SPI idea still needs a very similar location info fix. So we can split
the discussion about how to fix location info from the discussion
whether we prefer the jul bridge or a tomcat provided Log4J2 logger via SPI.
For the sake of completeness, here's the call stack we need to handle to
find the location info when using the Log4J2 jul bridge:
...
org.apache.logging.log4j.core.Logger.logMessage(Logger.java:147)
org.apache.logging.log4j.spi.ExtendedLoggerWrapper.logMessage(ExtendedLoggerWrapper.java:217)
org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1993)
org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1852)
org.apache.logging.log4j.jul.WrappedLogger.log(WrappedLogger.java:50)
org.apache.logging.log4j.jul.ApiLogger.log(ApiLogger.java:112)
org.apache.logging.log4j.jul.ApiLogger.logp(ApiLogger.java:132)
org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
org.apache.juli.logging.DirectJDKLog.info(DirectJDKLog.java:122)
-> here comes the wanted location
...
Regards,
Rainer
Class org.apache.juli.JuliLogEventFactory:
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.juli;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.impl.DefaultLogEventFactory;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
import org.apache.logging.log4j.message.Message;
import java.util.List;
public class JuliLogEventFactory extends DefaultLogEventFactory {
@Override
public LogEvent createEvent(final String loggerName, final Marker
marker, final String fqcn,
final Level level, final Message data,
final List<Property> properties,
final Throwable t) {
return new JuliLog4jLogEvent(loggerName, marker, fqcn, level,
data, properties, t);
}
public static class JuliLog4jLogEvent extends Log4jLogEvent {
private static final String juliLoggerName =
"org.apache.juli.logging.DirectJDKLog";
private StackTraceElement source = null;
public JuliLog4jLogEvent(final String loggerName, final Marker
marker, final String fqcn, final Level level,
final Message data, final
List<Property> properties, final Throwable t) {
super(loggerName, marker, fqcn, level, data, properties, t);
}
/**
* Returns the StackTraceElement for the caller. This will be
the entry that occurs right
* before the first occurrence of FQCN as a class name.
* @return the StackTraceElement for the caller.
*/
@Override
public StackTraceElement getSource() {
if (source != null) {
return source;
}
String loggerFqcn = getLoggerFqcn();
if (loggerFqcn == null || !isIncludeLocation()) {
return null;
}
source = calcLocation(loggerFqcn);
return source;
}
public static StackTraceElement calcLocation(final String
fqcnOfLogger) {
if (fqcnOfLogger == null) {
return null;
}
// LOG4J2-1029 new Throwable().getStackTrace is faster than
Thread.currentThread().getStackTrace().
final StackTraceElement[] stackTrace = new
Throwable().getStackTrace();
StackTraceElement last = null;
for (int i = stackTrace.length - 1; i > 0; i--) {
final String className = stackTrace[i].getClassName();
if (fqcnOfLogger.equals(className) ||
juliLoggerName.equals(className)) {
return last;
}
last = stackTrace[i];
}
return null;
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Romain Manni-Bucau <rm...@gmail.com>.
This has the issue but the fix is easy and 100% belonging to the Log impl
jar:
http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/java/org/apache/microwave/logging/log4j2/MicrowaveLogEventFactory.java
and
http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/resources/log4j2.component.properties
Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> | Blog
<https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
<http://www.tomitribe.com> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>
2016-10-25 16:38 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Am 25.10.2016 um 15:33 schrieb Romain Manni-Bucau:
>
>> Hi guys,
>>
>> since now tomcat has Log API as a SPI doing 2 is easy (
>> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk
>> /microwave-core/src/main/java/org/apache/microwave/logging/
>> tomcat/Log4j2Log.java)
>> and
>> just a drop-in jar setup so not sure it needs to be in tomcat default
>> delivery.
>>
>
> I tried to plug in Log4j2Log.java using SPI. It gets used, but it doesn't
> fix the problem. Now the location info points to Log4j2Log instead of
> DirectJDKLog. The Problem of one indirection layer to much above Log4Js
> has't changed.
>
> I think the jul log bridge removes one frame, which is the jul loger,
> ending up taking the DirectJDKLog which vcalls the jul logger as its
> location. Using your approach does no longer use jul, so log4j2 doesn't re
> move a frame and again takes the wrong class Log4j2Log as its location info.
>
> I think delegating is not enough, you actually need to implement the
> target API or extend a target implementation.
>
> Did you check the location info using the SPI approach?
>
> Regards,
>
> Rainer
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 25.10.2016 um 15:33 schrieb Romain Manni-Bucau:
> Hi guys,
>
> since now tomcat has Log API as a SPI doing 2 is easy (
> http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/java/org/apache/microwave/logging/tomcat/Log4j2Log.java)
> and
> just a drop-in jar setup so not sure it needs to be in tomcat default
> delivery.
I tried to plug in Log4j2Log.java using SPI. It gets used, but it
doesn't fix the problem. Now the location info points to Log4j2Log
instead of DirectJDKLog. The Problem of one indirection layer to much
above Log4Js has't changed.
I think the jul log bridge removes one frame, which is the jul loger,
ending up taking the DirectJDKLog which vcalls the jul logger as its
location. Using your approach does no longer use jul, so log4j2 doesn't
re move a frame and again takes the wrong class Log4j2Log as its
location info.
I think delegating is not enough, you actually need to implement the
target API or extend a target implementation.
Did you check the location info using the SPI approach?
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rémy Maucherat <re...@apache.org>.
2016-10-25 16:11 GMT+02:00 Rainer Jung <ra...@kippdata.de>:
> Am 25.10.2016 um 15:49 schrieb Rémy Maucherat:
>
>> 2016-10-25 15:33 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
>>
>> Hi guys,
>>>
>>> since now tomcat has Log API as a SPI doing 2 is easy (
>>> http://svn.apache.org/repos/asf/openwebbeans/microwave/
>>> trunk/microwave-core/src/main/java/org/apache/microwave/
>>> logging/tomcat/Log4j2Log.java)
>>> and
>>> just a drop-in jar setup so not sure it needs to be in tomcat default
>>> delivery.
>>>
>>
> I see. This sounds pretty simple.
>
> But if this is enough and done through reflection, it avoids the
>> dependency too.
>>
>
> Just that I understand: you mean the dependency on the Log4J jul bridge?
> Or some other dependency?
>
Yes, that's based on the example that was given, if the idea is to provide
support for more logging frameworks:
http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/java/org/apache/microwave/logging/tomcat/Log4j2Log.java
Rémy
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rainer Jung <ra...@kippdata.de>.
Am 25.10.2016 um 15:49 schrieb R�my Maucherat:
> 2016-10-25 15:33 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
>
>> Hi guys,
>>
>> since now tomcat has Log API as a SPI doing 2 is easy (
>> http://svn.apache.org/repos/asf/openwebbeans/microwave/
>> trunk/microwave-core/src/main/java/org/apache/microwave/
>> logging/tomcat/Log4j2Log.java)
>> and
>> just a drop-in jar setup so not sure it needs to be in tomcat default
>> delivery.
I see. This sounds pretty simple.
> But if this is enough and done through reflection, it avoids the
> dependency too.
Just that I understand: you mean the dependency on the Log4J jul bridge?
Or some other dependency?
> 1) isn't bad, the original idea was to use java.util.logging but add the
> classloading log manager to be able to log per webapp.
Although I never used the juli-per-webapp feature, we probably don't
want to loose it.
Regards,
Rainer
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Rémy Maucherat <re...@apache.org>.
2016-10-25 15:33 GMT+02:00 Romain Manni-Bucau <rm...@gmail.com>:
> Hi guys,
>
> since now tomcat has Log API as a SPI doing 2 is easy (
> http://svn.apache.org/repos/asf/openwebbeans/microwave/
> trunk/microwave-core/src/main/java/org/apache/microwave/
> logging/tomcat/Log4j2Log.java)
> and
> just a drop-in jar setup so not sure it needs to be in tomcat default
> delivery.
>
> But if this is enough and done through reflection, it avoids the
dependency too.
1) isn't bad, the original idea was to use java.util.logging but add the
classloading log manager to be able to log per webapp.
Rémy
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Romain Manni-Bucau <rm...@gmail.com>.
Hi guys,
since now tomcat has Log API as a SPI doing 2 is easy (
http://svn.apache.org/repos/asf/openwebbeans/microwave/trunk/microwave-core/src/main/java/org/apache/microwave/logging/tomcat/Log4j2Log.java)
and
just a drop-in jar setup so not sure it needs to be in tomcat default
delivery.
Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> | Blog
<https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
<http://www.tomitribe.com> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>
2016-10-25 15:28 GMT+02:00 Mark Thomas <ma...@apache.org>:
> On 25/10/2016 14:17, Rainer Jung wrote:
> > Hi everyone,
> >
> > when using TC 8.5 with the Log4J2 jul bridge the location info in the
> > Log4J output points to the juli class DirectJDKLog instead of the Tomcat
> > class with the juli log call. Only the category/logger name is correct:
> >
> > %c: org.apache.catalina.core.StandardServer (Example, correct)
> > %C: org.apache.juli.logging.DirectJDKLog
> > %l: org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
> > %M: log
> > %F: DirectJDKLog.java
> > %L: 179
> >
> > The jul bridge does not try to fully populate al possible location info,
> > but instead only the category name. Log4J then later gets the log
> > location from the stack frame that calls the jul bridge which always
> > gives org.apache.juli.logging.DirectJDKLog.
> >
> > It seems we either need to directly call the jul bridge without an
> > intermediate logging impl class, or the Log4J2 jul bridge must be made
> > more complex.
> >
> > Any opinion? Ideas?
>
> I did look at whether or not we could remove the use of DirectJDKLog -
> essentially reducing JULI to the custom LogManager. My conclusion at the
> time was it was possible but was a whole lot of effort for very little
> benefit. Maybe this tips the balance?
>
> The other option would be to provide a dedicated log4j2 adadptor - maybe
> along with appropriate adapters for other logging frameworks as well.
>
> > I know that the location info is expensive to get, but failing to
> > support the correct location info is IMHO bad. The old adapter solution
> > supported correct location info in log4j.
>
> I think we have two options:
>
> 1. Code to just java.util.logging as sufficient and let the logging
> frameworks deal with hooking in to java.util.logging. This is
> essentially the option that removes code.
>
> 2. Provide an adaptor for at least log4j2 and possible other frameworks.
> This is essentially the option that adds code.
>
> Option 1 means less code but less flexibility. Option 2 is more code but
> what we get in return is more flexibility maybe implementation options
> for better performance.
>
> Another advantage of 1 is that it removes JULI as a dependency from much
> of out code. This could make it simpler for others to re-use.
>
> Personally, I lean towards 1. but I'm not going to object if someone
> wants to pursue 2.
>
> Mark
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>
Re: TC 8.5 and Log4J2 via Juli: Wrong location info
Posted by Mark Thomas <ma...@apache.org>.
On 25/10/2016 14:17, Rainer Jung wrote:
> Hi everyone,
>
> when using TC 8.5 with the Log4J2 jul bridge the location info in the
> Log4J output points to the juli class DirectJDKLog instead of the Tomcat
> class with the juli log call. Only the category/logger name is correct:
>
> %c: org.apache.catalina.core.StandardServer (Example, correct)
> %C: org.apache.juli.logging.DirectJDKLog
> %l: org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:179)
> %M: log
> %F: DirectJDKLog.java
> %L: 179
>
> The jul bridge does not try to fully populate al possible location info,
> but instead only the category name. Log4J then later gets the log
> location from the stack frame that calls the jul bridge which always
> gives org.apache.juli.logging.DirectJDKLog.
>
> It seems we either need to directly call the jul bridge without an
> intermediate logging impl class, or the Log4J2 jul bridge must be made
> more complex.
>
> Any opinion? Ideas?
I did look at whether or not we could remove the use of DirectJDKLog -
essentially reducing JULI to the custom LogManager. My conclusion at the
time was it was possible but was a whole lot of effort for very little
benefit. Maybe this tips the balance?
The other option would be to provide a dedicated log4j2 adadptor - maybe
along with appropriate adapters for other logging frameworks as well.
> I know that the location info is expensive to get, but failing to
> support the correct location info is IMHO bad. The old adapter solution
> supported correct location info in log4j.
I think we have two options:
1. Code to just java.util.logging as sufficient and let the logging
frameworks deal with hooking in to java.util.logging. This is
essentially the option that removes code.
2. Provide an adaptor for at least log4j2 and possible other frameworks.
This is essentially the option that adds code.
Option 1 means less code but less flexibility. Option 2 is more code but
what we get in return is more flexibility maybe implementation options
for better performance.
Another advantage of 1 is that it removes JULI as a dependency from much
of out code. This could make it simpler for others to re-use.
Personally, I lean towards 1. but I'm not going to object if someone
wants to pursue 2.
Mark
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org