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