Hi Mark,

> >I think there are a number of options for this class that
> can be explored,
> >such as possibly using a distinct logger repository per web
> >application/servlet/etc.

Actually, I have written a Log4jInit servlet that, in addition, uses a Log4jCRS (Log4j Contextual Repository Selector) class to create a distinct logger repository per webapp just like you mentioned. It is heavily based up on Ceki's doc at http://qos.ch/containers/sc.html but with some definite differences. You can see the code here:

http://barracuda.enhydra.org/software/cvs/cvsweb.cgi/Projects/EnhydraOrg/toolsTech/Barracuda/src/org/enhydra/barracuda/log4j/Log4jCRS.java?rev=1.1&content-type=text/x-cvsweb-markup

Here is the Log4jInit class that uses it. Currently, it provides options to load a properties or xml config file, provide optional configureAndWatch() functionality, takes into account whether the webapp is being served from a .war file or off the file system and uses only streams to load configuration if it is from a .war file (you can't use File IO out of an archive), and drops back to default configuration if all else fails. it is pretty failproof. Oh, and the best part; it uses Log4jCRS to create a distinct logger repository for each application allowing one to put log4j.jar in Tomcat's common/lib directory and not having to worry about walking all over another app's logj4 configuration. I have only tested this in Tomcat, but it should work with other appservers with similar classloading schemes.

http://barracuda.enhydra.org/software/cvs/cvsweb.cgi/Projects/EnhydraOrg/toolsTech/Barracuda/src/org/enhydra/barracuda/webapp/log4j/Log4jInit.java?rev=1.1&content-type=text/x-cvsweb-markup

here is how it is configured in the web.xml:

<servlet>
<servlet-name>log4j-init</servlet-name>
<servlet-class>org.enhydra.barracuda.webapp.log4j.Log4jInit</servlet-class>
<init-param>
<!-- relative path to config file within current webapp -->
<param-name>log4j-config</param-name>
<param-value>WEB-INF/log4j.xml</param-value>
</init-param>
<init-param>
<!-- config file re-reading specified in milliseconds...
Note that if the webapp is served directly from the
.war file, configureAndWatch() cannot be used because
it requires a system file path. In that case, this
param will be ignored. Set to 0 or don't specify this
param to do a normal configure(). -->
<param-name>log4j-cron</param-name>
<param-value>5000</param-value>
</init-param>
<!-- optional param for use with a File Appender.
Specifies a path to be read from a log4j xml
config file as a system property. The property name is
dynamically generated and takes on the following pattern:
[webapp name].log.home
In Barracuda's case, it would be "Barracuda.log.home".
The path defaults to WEB-INF/logs directory, which is created
if it doesn't exist, unless the webapp is running directly
from a .war file.
Note that, if specified, the value is an absolute path, not
relative to the webapp. -->
<!-- <init-param>
<param-name>log4j-log-home</param-name>
<param-value>/usr/local/logs/tomcat</param-value>
</init-param> -->
<load-on-startup>1</load-on-startup>
</servlet>


Also, here is a ServletContextListener called Log4jApplicationWatch which cleans up log4j at application shutdown making sure that all loggers and appenders are cleaned up. For instance, this makes sure that a FileAppender releases its handle on the file that the application was logging to. If this cleanup is not done, the file stays locked even after the app is shutdown (by Tomcat's manager app, in my case).

http://barracuda.enhydra.org/software/cvs/cvsweb.cgi/Projects/EnhydraOrg/toolsTech/Barracuda/src/org/enhydra/barracuda/webapp/log4j/Log4jApplicationWatch.java?rev=1.1&content-type=text/x-cvsweb-markup

here is how it is configured in the web.xml:

<listener>
<listener-class>
org.enhydra.barracuda.webapp.log4j.Log4jApplicationWatch
</listener-class>
</listener>


The one issue with putting Log4jInit in the Log4j.jar distribution, at least the way this Log4jInit works with Log4jCRS, is that Log4jInit and Log4jApplicationWatch *have* to exist in the WEB-INF/lib of any webapp using them. This is because the logger repositories created and stored by Log4jCRS are keyed by classloader. So if you want to create a new LoggerRepository you need to do this:

Log4jCRS crs = new Log4jCRS();
crs.initLoggerRepository();

initLoggerRepository in Log4jCRS looks like this:

public void initLoggerRepository() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
setGetLoggerRepository(cl);
}

And if you want to get a reference to the current logger repository for the webapp (in the case where Log4jApplicationWatch needs to shut down that logger repository), you need to do this:

ClassLoader cl = Thread.currentThread().getContextClassLoader();
Log4jCRS crs = Log4jCRS.getCRS(cl);


So, as you can see, in order to create/get the logger repository for a webapp, the Log4jCRS instantiation must be done in the webapp classloader of the current web application (ie.... WEB-INF/lib or WEB-INF/classes) in order to have the appropriate classloader keyed for the LoggerRepository.

Log4jCRS doesn't need to exist in WEB-INF/lib. In fact, it must exist in a classloader that also contains log4j.jar in order to work properly because both Log4jCRS and log4j.jar must be able to see each other for log4j.jar to call getLoggerRepository since Log4jCRS is now consider the LoggerRepositorySelector for the current logger repository. So, if you have Log4jCRS in your webapp classloader, you better make sure that Log4j.jar is also in the webapp classloader. However, if Log4jCRS is in a parent classloader such as (in Tomcat) shared/lib then you'd better make sure that either another copy of Log4jCRS *and* log4j.jar exist in your WEB-INF/lib OR that neither Log4jCRS *nor* log4j.jar exist in WEB-INF/lib and that log4j.jar exists alongside Log4jCRS in the parent classloader (either in shared/lib or common/lib. Tomcat's commons-logging doesn't like log4j.jar in shared/lib, but rather common/lib so I'd put it there. Log4jCRS can be in either shared/lib or common/lib when log4j.jar is in common/lib).

If that sounded a little confusing, it wouldn't be if Log4jCRS was included as part of the Log4j distribution. In fact, my hope is that maybe you will consider my version of Log4jCRS for inclusion in the standard log4j.jar distribution. The Log4jInit servlet and Log4jApplicationWatch servlet context listener really can't be included in log4j.jar for the reasons stated above. I suppose if someone comes up with a way to work around the issues I pointed out, then they could also be included in the distribution. I'm always open to improvements!

Anyway, if anyone is interested in any of this for inclusion, the licence can be whatever Log4j prefers (apache license?). Right now, all of them are assumed to be under the LGPL.

Let me know if anyone is interested.

Jake

At 06:19 PM 11/13/2002 -0800, you wrote:
Actually, the usefulness of this servlet goes beyond the initial
configuration code.  This servlet could also be used to view/modify the
configuration (ie view/set levels for loggers, etc) for the given web
application it is deployed for.  I'm sure others have brought this up, but
some of my current work has really brought this home.

-Mark

> -----Original Message-----
> From: Ceki Gülcü [mailto:ceki@;qos.ch]
> Sent: Monday, October 07, 2002 4:53 AM
> To: Log4J Developers List
> Subject: Re: [VOTE] Proposal: Log4Init servlet class
>
>
>
> It really depends on what is contained in Log4jInit servlet.
> If it is just
> a copy of what is in the existing log4j manual then the added
> value will be
> somewhat limited. However, if this addition is the harbinger
> of new log4j
> developments in the servlet arena, I welcome the effort.
>
> Another worthy effort is JMX support in log4j. Here is a call
> for volunteers:
> http://marc.theaimsgroup.com/?l=log4j-dev&m=102391028026244&w=2
>
> See JMX snapshots at:
>
> http://jakarta.apache.org/~ceki/jmx1.jpg
> http://jakarta.apache.org/~ceki/jmx2.jpg
> http://jakarta.apache.org/~ceki/jmx3.jpg
>
>
>
> At 21:52 06.10.2002 -0700, [EMAIL PROTECTED] wrote:
> >In the quest of finding more things to do that one has time
> for, I propose
> >that we explore the inclusion of a Log4jInit servlet class
> in the official
> >log4j library.  This would be a servlet class that can be
> used to initialize
> >log4j in a web application.  Everyone seems to have their
> own version of one
> >that all do the same basic stuff.
> >
> >I am making this proposal because if this class is used so
> often, then I
> >think a basic version should be available in the official
> log4j library for
> >general use or for specific extension by developers.  It
> will make log4j
> >"easier" to use because it will have a useful off-the-shelf class
> >specifically designed for web applications.
> >
> >However, I would like this component to be "owned" by
> someone else that will
> >put the energy into it.  If this person is not a committer,
> then I volunteer
> >to "champion" and review the code, and make sure it gets
> committed into cvs
> >after review.  But my v1.3 plate is full with plugins,
> receivers, watchdogs,
> >and filters.
> >
> >A number of folks have stated an interest in contributing to
> log4j.  Here's
> >your chance to create something that almost every log4j web
> application
> >based developer will use.  If no one steps up, then it will
> just wait until
> >one of us has the time.
> >
> >I think there are a number of options for this class that
> can be explored,
> >such as possibly using a distinct logger repository per web
> >application/servlet/etc.  There may be other related
> components that could
> >be considered.
> >
> >But first, what do the other committers think?
> >
> >+1
> >
> >-Mark
> >
> >
> >--
> >To unsubscribe, e-mail:
> <mailto:log4j-dev-unsubscribe@;jakarta.apache.org>
> >For additional commands, e-mail:
> <mailto:log4j-dev-help@;jakarta.apache.org>
>
> --
> Ceki
>
> TCP implementations will follow a general principle of robustness: be
> conservative in what you do, be liberal in what you accept from
> others. -- Jon Postel, RFC 793
>
>
>
> --
> To unsubscribe, e-mail:
> <mailto:log4j-dev-unsubscribe@;jakarta.apache.org>
> For additional commands, e-mail:
> <mailto:log4j-dev-help@;jakarta.apache.org>
>

--
To unsubscribe, e-mail:   <mailto:log4j-dev-unsubscribe@;jakarta.apache.org>
For additional commands, e-mail: <mailto:log4j-dev-help@;jakarta.apache.org>

Reply via email to