git-svn-id: https://svn.apache.org/repos/asf/commons/proper/logging/trunk@581090 13f79535-47bb-0310-9956-ffa450edef68
833 lines
37 KiB
XML
833 lines
37 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<!--
|
|
|
|
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.
|
|
|
|
-->
|
|
|
|
<document>
|
|
|
|
<properties>
|
|
<title>User Guide</title>
|
|
<author email="dev@commons.apache.org">Commons Documentation Team</author>
|
|
</properties>
|
|
|
|
<body>
|
|
<section name='Contents'>
|
|
<p>
|
|
<ol>
|
|
<li><a href='#Introduction'>Introduction</a></li>
|
|
<li><a href='#Quick Start'>Quick Start</a>
|
|
<ol>
|
|
<li><a href='#Configuration'>Configuration</a></li>
|
|
<li>
|
|
<a href='#Configuring The Underlying Logging System'>Configuring The Underlying Logging System</a>
|
|
</li>
|
|
<li>
|
|
<a href='#Configuring Log4J'>Configuring Log4J</a>
|
|
</li>
|
|
</ol>
|
|
</li>
|
|
<li><a href='#Developing With JCL'>Developing With JCL</a>
|
|
<ol>
|
|
<li><a href='#Obtaining a Log Object'>Obtaining a Log Object</a></li>
|
|
<li><a href='#Logging a Message'>Logging a Message</a></li>
|
|
<li><a href='#Serialization Issues'>Serialization Issues</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href='#Jars Included in the Standard Distribution'>Jars Included in the Standard Distribution</a>
|
|
<ol>
|
|
<li><a href='#commons-logging.jar'>commons-logging.jar</a></li>
|
|
<li><a href='#commons-logging-api.jar'>commons-logging-api.jar</a></li>
|
|
<li><a href='#commons-logging-adapters.jar'>commons-logging-adapters.jar</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href='#JCL Best Practices'>JCL Best Practices</a></li>
|
|
<li><a href='#Best Practices (General)'>Best Practices (General)</a>
|
|
<ol>
|
|
<li><a href='#Code Guards'>Code Guards</a></li>
|
|
<li><a href='#Message Priorities/Levels'>Message Priorities/Levels</a></li>
|
|
<li><a href='#Default Message Priority/Level'>Default Message Priority/Level</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href='#Best Practices (Enterprise)'>Best Practices (Enterprise)</a>
|
|
<ol>
|
|
<li><a href='#Logging Exceptions'>Logging Exceptions</a></li>
|
|
<li><a href='#When Info Level Instead of Debug?'>When Info Level Instead of Debug?</a></li>
|
|
<li><a href='#More Control of Enterprise Exception Logging'>More Control of Enterprise Exception Logging</a></li>
|
|
<li><a href='#National Language Support And Internationalization'>National Language Support And Internationalization</a></li>
|
|
<li><a href='#Classloader and Memory Management'>Classloader and Memory Management</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href='#Extending Commons Logging'>Extending Commons Logging</a>
|
|
<ol>
|
|
<li><a href='#Contract'>Contract</a></li>
|
|
<li><a href='#Creating a Log Implementation'>Creating a Log Implementation</a></li>
|
|
<li><a href='#Creating A LogFactory Implementation'>Creating A LogFactory Implementation</a></li>
|
|
</ol>
|
|
</li>
|
|
<li><a href='#A%20Quick%20Guide%20To%20Simple%20Log'>A Quick Guide To Simple Log</a>
|
|
</li>
|
|
<li><a href='#Frequently Asked Questions'>Frequently Asked Questions</a>
|
|
</li>
|
|
</ol>
|
|
</p>
|
|
</section>
|
|
<section name="Introduction">
|
|
<p>
|
|
The Apache Commons Logging (JCL) provides a <code>Log</code> interface that
|
|
is intended to be both light-weight and an independent abstraction of other logging toolkits.
|
|
It provides the middleware/tooling developer with a simple
|
|
logging abstraction, that allows the user (application developer) to plug in
|
|
a specific logging implementation.
|
|
</p>
|
|
<p>JCL provides thin-wrapper <code>Log</code> implementations for
|
|
other logging tools, including
|
|
<a href="http://logging.apache.org/log4j/docs/index.html">Log4J</a>,
|
|
<a href="http://avalon.apache.org/logkit/index.html">Avalon LogKit</a>
|
|
(the Avalon Framework's logging infrastructure),
|
|
JDK 1.4, and an implementation of JDK 1.4 logging APIs (JSR-47) for pre-1.4
|
|
systems.
|
|
The interface maps closely to Log4J and LogKit.
|
|
</p>
|
|
<p>
|
|
Familiarity with high-level details of the relevant Logging implementations is presumed.
|
|
</p>
|
|
</section>
|
|
<section name="Quick Start">
|
|
<p>
|
|
As far as possible, JCL tries to be as unobtrusive as possible.
|
|
In most cases, including the (full) <code>commons-logging.jar</code> in the classpath
|
|
should result in JCL configuring itself in a reasonable manner.
|
|
There's a good chance that it'll guess your preferred logging system and you won't
|
|
need to do any configuration at all!
|
|
</p><p>
|
|
Note, however, that if you have a particular preference then providing a simple
|
|
<code>commons-logging.properties</code> file which specifies the concrete logging library to be
|
|
used is recommended, since (in this case) JCL will log only to that system
|
|
and will report any configuration problems that prevent that system being used.
|
|
</p>
|
|
<subsection name='Configuration'>
|
|
<p>
|
|
There are two base abstractions used by JCL: <code>Log</code>
|
|
(the basic logger) and <code>LogFactory</code> (which knows how to create <code>Log</code>
|
|
instances). Specifying a particular Log implementation is very useful (whether that is
|
|
one provided by commons-logging or a user-defined one). Specifying a
|
|
<code>LogFactory</code> implementation other than the default is a subject for
|
|
advanced users only, so will not be addressed here.
|
|
</p>
|
|
<p>
|
|
The default <code>LogFactory</code> implementation uses the following discovery process
|
|
to determine what type of <code>Log</code> implementation it should use
|
|
(the process terminates when the first positive match - in order - is found):
|
|
</p>
|
|
|
|
<ol>
|
|
<li>
|
|
Look for a configuration attribute of this factory named
|
|
<code>org.apache.commons.logging.Log</code> (for backwards compatibility to
|
|
pre-1.0 versions of this API, an attribute
|
|
<code>org.apache.commons.logging.log</code> is also consulted).
|
|
<p>
|
|
Configuration attributes can be set explicitly by java code, but they are more
|
|
commonly set by placing a file named commons-logging.properties in the classpath.
|
|
When such a file exists, every entry in the properties file becomes an "attribute"
|
|
of the LogFactory. When there is more than one such file in the classpath, releases
|
|
of commons-logging prior to 1.1 simply use the first one found. From release 1.1,
|
|
each file may define a <code>priority</code> key, and the file with
|
|
the highest priority is used (no priority definition implies priority of zero).
|
|
When multiple files have the same priority, the first one found is used.
|
|
</p>
|
|
<p>
|
|
Defining this property in a commons-logging.properties file is the recommended
|
|
way of explicitly selecting a Log implementation.
|
|
</p>
|
|
</li>
|
|
<li>
|
|
Look for a system property named
|
|
<code>org.apache.commons.logging.Log</code> (for backwards
|
|
compatibility to pre-1.0 versions of this API, a system property
|
|
<code>org.apache.commons.logging.log</code> is also consulted).
|
|
</li>
|
|
<li>
|
|
If the Log4J logging system is available in the application
|
|
class path, use the corresponding wrapper class
|
|
(<a href="http://commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/Log4JLogger.html">Log4JLogger</a>).
|
|
</li>
|
|
<li>
|
|
If the application is executing on a JDK 1.4 system, use
|
|
the corresponding wrapper class
|
|
(<a href="http://commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/Jdk14Logger.html">Jdk14Logger</a>).
|
|
</li>
|
|
<li>
|
|
Fall back to the default simple logging wrapper
|
|
(<a href="http://commons.apache.org/logging/apidocs/org/apache/commons/logging/impl/SimpleLog.html">SimpleLog</a>).
|
|
</li>
|
|
</ol>
|
|
<p>
|
|
Consult the JCL javadocs for details of the various <code>Log</code>
|
|
implementations that ship with the component. (The discovery process is also covered in more
|
|
detail there.)
|
|
</p>
|
|
</subsection>
|
|
<subsection name='Configuring The Underlying Logging System'>
|
|
<p>
|
|
The JCL SPI
|
|
can be configured to use different logging toolkits (see <a href='#Configuration'>above</a>).
|
|
JCL provides only a bridge for writing log messages. It does not (and will not) support any
|
|
sort of configuration API for the underlying logging system.
|
|
</p>
|
|
<p>
|
|
Configuration of the behavior of the JCL ultimately depends upon the
|
|
logging toolkit being used. Please consult the documentation for the chosen logging system.
|
|
</p>
|
|
<subsection name='Configuring Log4J'>
|
|
<p>
|
|
Log4J is a very commonly used logging implementation (as well as being the JCL primary default),
|
|
so a <i>few</i> details are presented herein to get the developer/integrator going.
|
|
Please see the <a href='http://logging.apache.org/log4j/docs/index.html'>Log4J Home</a> for more details
|
|
on Log4J and it's configuration.
|
|
</p>
|
|
<p>
|
|
Configure Log4J using system properties and/or a properties file:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<strong>log4j.configuration=<em>log4j.properties</em></strong>
|
|
Use this system property to specify the name of a Log4J configuration file.
|
|
If not specified, the default configuration file is <i>log4j.properties</i>.
|
|
</li>
|
|
<li>
|
|
<strong>log4j.rootCategory=<i>priority</i> [, <i>appender</i>]*</strong>
|
|
</li>
|
|
Set the default (root) logger priority.
|
|
<li>
|
|
<strong>log4j.logger.<i>logger.name</i>=<i>priority</i></strong>
|
|
Set the priority for the named logger
|
|
and all loggers hierarchically lower than, or below, the
|
|
named logger.
|
|
<i>logger.name</i> corresponds to the parameter of
|
|
<code>LogFactory.getLog(<i>logger.name</i>)</code>,
|
|
used to create the logger instance. Priorities are:
|
|
<code>DEBUG</code>,
|
|
<code>INFO</code>,
|
|
<code>WARN</code>,
|
|
<code>ERROR</code>,
|
|
or <code>FATAL</code>.
|
|
<br/>
|
|
Log4J understands hierarchical names,
|
|
enabling control by package or high-level qualifiers:
|
|
<code>log4j.logger.org.apache.component=DEBUG</code>
|
|
will enable debug messages for all classes in both
|
|
<code>org.apache.component</code>
|
|
and
|
|
<code>org.apache.component.sub</code>.
|
|
Likewise, setting
|
|
<code>log4j.logger.org.apache.component=DEBUG</code>
|
|
will enable debug message for all 'component' classes,
|
|
but not for other Apache projects.
|
|
</li>
|
|
<li>
|
|
<strong>log4j.appender.<i>appender</i>.Threshold=<i>priority</i></strong>
|
|
</li>
|
|
Log4J <i>appenders</i> correspond to different output devices:
|
|
console, files, sockets, and others.
|
|
If appender's <i>threshold</i>
|
|
is less than or equal to the message priority then
|
|
the message is written by that appender.
|
|
This allows different levels of detail to be appear
|
|
at different log destinations.
|
|
For example: one can capture DEBUG (and higher) level information in a logfile,
|
|
while limiting console output to INFO (and higher).
|
|
</ul>
|
|
</subsection>
|
|
</subsection>
|
|
</section>
|
|
<section name='Developing With JCL'>
|
|
<subsection name="Obtaining a Log Object">
|
|
<p>
|
|
To use the JCL SPI from a Java class,
|
|
include the following import statements:
|
|
</p>
|
|
<ul>
|
|
<code>
|
|
import org.apache.commons.logging.Log;
|
|
<br/>
|
|
import org.apache.commons.logging.LogFactory;
|
|
<br/>
|
|
</code>
|
|
</ul>
|
|
<p>
|
|
Note that some components using JCL may
|
|
either extend Log,
|
|
or provide a component-specific LogFactory implementation.
|
|
Review the component documentation for guidelines
|
|
on how commons-logging should be used in such components.
|
|
</p>
|
|
<p>
|
|
For each class definition, declare and initialize a
|
|
<code>log</code> attribute as follows:
|
|
</p>
|
|
<ul>
|
|
<source>
|
|
public class CLASS
|
|
{
|
|
private Log log = LogFactory.getLog(CLASS.class);
|
|
...
|
|
;
|
|
</source>
|
|
</ul>
|
|
<p>
|
|
Note that for application code, declaring the log member as "static" is more
|
|
efficient as one Log object is created per class, and is recommended.
|
|
However this is not safe to do for a class which may be deployed via a "shared"
|
|
classloader in a servlet or j2ee container or similar environment. If the class
|
|
may end up invoked with different thread-context-classloader values set then the
|
|
member must <i>not</i> be declared static. The use of "static" should therefore
|
|
be avoided in code within any "library" type project.
|
|
</p>
|
|
</subsection>
|
|
<subsection name="Logging a Message">
|
|
<p>
|
|
Messages are logged to a <em>logger</em>, such as <code>log</code>
|
|
by invoking a method corresponding to <em>priority</em>.
|
|
The <code>org.apache.commons.logging.Log</code> interface defines the
|
|
following methods for use
|
|
in writing log/trace messages to the log:
|
|
</p>
|
|
<ul>
|
|
<source>
|
|
log.fatal(Object message);
|
|
log.fatal(Object message, Throwable t);
|
|
log.error(Object message);
|
|
log.error(Object message, Throwable t);
|
|
log.warn(Object message);
|
|
log.warn(Object message, Throwable t);
|
|
log.info(Object message);
|
|
log.info(Object message, Throwable t);
|
|
log.debug(Object message);
|
|
log.debug(Object message, Throwable t);
|
|
log.trace(Object message);
|
|
log.trace(Object message, Throwable t);
|
|
</source>
|
|
</ul>
|
|
<p>
|
|
Semantics for these methods are such that it is expected
|
|
that the severity, from highest to lowest, of messages is ordered as above.
|
|
</p>
|
|
<p>
|
|
In addition to the logging methods, the following are provided for code guards:
|
|
</p>
|
|
<ul>
|
|
<source>
|
|
log.isFatalEnabled();
|
|
log.isErrorEnabled();
|
|
log.isWarnEnabled();
|
|
log.isInfoEnabled();
|
|
log.isDebugEnabled();
|
|
log.isTraceEnabled();
|
|
</source>
|
|
</ul>
|
|
</subsection>
|
|
<subsection name="Serialization Issues">
|
|
<p>Prior to release 1.0.4, none of the standard Log implementations were
|
|
Serializable. If you are using such a release and have a Serializable class
|
|
with a member that is of type Log then it is necessary to declare
|
|
that member to be transient and to ensure that the value is restored on
|
|
deserialization. The recommended approach is to define a custom
|
|
readObject method on the class which reinitializes that member.</p>
|
|
<p>In release 1.0.4, all standard Log implementations are Serializable. This
|
|
means that class members of type Log do <i>not</i> need to be declared transient;
|
|
on deserialization the Log object will "rebind" to the same category for the
|
|
same logging library. Note that the same underlying logging library will be
|
|
used on deserialization as was used in the original object, even if the
|
|
application the object was deserialized into is using a different logging
|
|
library. There is one exception; LogKitLogger (adapter for the Avalon LogKit
|
|
library) is not Serializable for technical reasons.</p>
|
|
<p>Custom Log implementations not distributed with commons-logging may
|
|
or may not be Serializable. If you wish your code to be compatible with
|
|
any arbitrary log adapter then you should follow the advice given above
|
|
for pre-1.0.4 releases.</p>
|
|
</subsection>
|
|
</section>
|
|
<section name="Jars Included in the Standard Distribution">
|
|
<subsection name="commons-logging.jar">
|
|
<p>
|
|
The <code>commons-logging.jar</code> file includes the JCL API, the default
|
|
<code>LogFactory</code> implemenation and thin-wrapper <code>Log</code>
|
|
implementations for
|
|
<a href="http://logging.apache.org/log4j/docs/index.html">Log4J</a>,
|
|
<a href="http://avalon.apache.org/logkit/index.html">Avalon LogKit</a>,
|
|
the Avalon Framework's logging infrastructure,
|
|
JDK 1.4, as well as an implementation of JDK 1.4 logging APIs (JSR-47) for
|
|
pre-1.4 systems.
|
|
</p>
|
|
<p>
|
|
In most cases, including <code>commons-logging.jar</code> and your preferred
|
|
logging implementation in the classpath should be all that is required to
|
|
use JCL.
|
|
</p>
|
|
</subsection>
|
|
<subsection name="commons-logging-api.jar">
|
|
<p>
|
|
The <code>commons-logging-api.jar</code> file includes the JCL API and the
|
|
default <code>LogFactory</code> implementation as well as the built-in
|
|
<code>Log</code> implementations SimpleLog and NoOpLog. However it does not
|
|
include the wrapper <code>Log</code> implementations that require additional
|
|
libraries such as <code>Log4j</code>, <code>Avalon</code> and
|
|
<code>Lumberjack</code>.
|
|
</p>
|
|
<p>
|
|
This jar is intended for use by projects that recompile the commons-logging
|
|
source using alternate java environments, and cannot compile against all of
|
|
the optional libraries that the Apache release of commons-logging supports.
|
|
Because of the reduced dependencies of this jarfile, such projects should be
|
|
able to create an equivalent of this library with fewer difficulties.
|
|
</p>
|
|
<p>
|
|
This jar is also useful for build environments that automatically track
|
|
dependencies, and thus have difficulty with the concept that the main
|
|
commons-logging.jar has "optional" dependencies on various logging
|
|
implementations that can safely go unsatisfied at runtime.
|
|
</p>
|
|
</subsection>
|
|
<subsection name="commons-logging-adapters.jar">
|
|
<p>
|
|
The <code>commons-logging-adapters.jar</code> file includes only adapters
|
|
to third-party logging implementations, and none of the core commons-logging
|
|
framework. As such, it cannot be used alone; either commons-logging.jar or
|
|
commons-logging-api.jar must also be present in the classpath.
|
|
</p>
|
|
<p>
|
|
This library will not often be used; it is only intended for situations where
|
|
a container has deployed commons-logging-api.jar in a shared classpath but a
|
|
webapp wants to bind logging to one of the external logging implementations
|
|
that the api jar does not include. In this situation, deploying the
|
|
commons-logging.jar file within the webapp can cause problems as this leads to
|
|
duplicates of the core commons-logging classes (Log, LogFactory, etc) in
|
|
the classpath which in turn can cause unpleasant ClassCastException exceptions
|
|
to occur. Deploying only the adapters avoids this problem.
|
|
</p>
|
|
</subsection>
|
|
</section>
|
|
<section name='JCL Best Practices'>
|
|
<p>
|
|
Best practices for JCL are presented in two categories:
|
|
General and Enterprise.
|
|
The general principles are fairly clear.Enterprise practices are a bit more involved
|
|
and it is not always as clear as to why they are important.
|
|
</p>
|
|
<p>
|
|
Enterprise best-practice principles apply to middleware components
|
|
and tooling that is expected to execute in an "Enterprise" level
|
|
environment.
|
|
These issues relate to Logging as Internationalization,
|
|
and fault detection.
|
|
Enterprise requires more effort and planning, but are strongly encouraged (if not required)
|
|
in production level systems. Different corporate enterprises/environments have different
|
|
requirements, so being flexible always helps.
|
|
</p>
|
|
</section>
|
|
<section name='Best Practices (General)'>
|
|
<subsection name='Code Guards'>
|
|
<p>
|
|
Code guards are typically used to guard code that
|
|
only needs to execute in support of logging,
|
|
that otherwise introduces undesirable runtime overhead
|
|
in the general case (logging disabled).
|
|
Examples are multiple parameters, or expressions (e.g. string + " more") for parameters.
|
|
Use the guard methods of the form <code>log.is<<i>Priority</i>>()</code> to verify
|
|
that logging should be performed, before incurring the overhead of the logging method call.
|
|
Yes, the logging methods will perform the same check, but only after resolving parameters.
|
|
</p>
|
|
</subsection>
|
|
<subsection name='Message Priorities/Levels'>
|
|
<p>
|
|
It is important to ensure that log message are
|
|
appropriate in content and severity.
|
|
The following guidelines are suggested:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<b>fatal</b> - Severe errors that cause premature termination.
|
|
Expect these to be immediately visible on a status console.
|
|
See also <a HREF="#National%20Language%20Support%20And%20Internationalization">
|
|
Internationalization</a>.
|
|
</li>
|
|
<li>
|
|
<b>error</b> - Other runtime errors or unexpected conditions.
|
|
Expect these to be immediately visible on a status console.
|
|
See also <a HREF="#National%20Language%20Support%20And%20Internationalization">
|
|
Internationalization</a>.
|
|
</li>
|
|
<li>
|
|
<b>warn</b> - Use of deprecated APIs, poor use of API, 'almost' errors,
|
|
other runtime situations that are undesirable or unexpected, but not
|
|
necessarily "wrong".
|
|
Expect these to be immediately visible on a status console.
|
|
See also <a HREF="#National%20Language%20Support%20And%20Internationalization">
|
|
Internationalization</a>.
|
|
</li>
|
|
<li>
|
|
<b>info</b> - Interesting runtime events (startup/shutdown).
|
|
Expect these to be immediately visible on a console,
|
|
so be conservative and keep to a minimum.
|
|
See also <a HREF="#National%20Language%20Support%20And%20Internationalization">
|
|
Internationalization</a>.
|
|
</li>
|
|
<li>
|
|
<b>debug</b> - detailed information on the flow through the system.
|
|
Expect these to be written to logs only.
|
|
</li>
|
|
<li>
|
|
<b>trace</b> - more detailed information.
|
|
Expect these to be written to logs only.
|
|
</li>
|
|
</ul>
|
|
</subsection>
|
|
<subsection name='Default Message Priority/Level'>
|
|
<p>
|
|
By default the message priority should be no lower than <b>info</b>.
|
|
That is, by default <b>debug</b> message should not be seen in the logs.
|
|
</p>
|
|
</subsection>
|
|
</section>
|
|
<section name='Best Practices (Enterprise)'>
|
|
<subsection name='Logging Exceptions'>
|
|
<p>
|
|
The general rule in dealing with exceptions is to assume that
|
|
the user (developer using a tooling/middleware API) isn't going
|
|
to follow the rules.
|
|
Since any problems that result are going to be assigned to you,
|
|
it's in your best interest to be prepared with the proactive
|
|
tools necessary to demonstrate that your component works correctly,
|
|
or at worst that the problem can be analyzed from your logs.
|
|
For this discussion, we must make a distinction between different types of exceptions
|
|
based on what kind of boundaries they cross:
|
|
</p>
|
|
<ul>
|
|
<li>
|
|
<b>External Boundaries - Expected Exceptions</b>.
|
|
This classification includes exceptions such as <code>FileNotFoundException</code>
|
|
that cross API/SPI boundaries, and are exposed to the user of a component/toolkit.
|
|
These are listed in the 'throws' clause of a method signature.
|
|
<br/>
|
|
Appropriate handling of these exceptions depends upon the type
|
|
of code you are developing.
|
|
API's for utility functions and tools should log these at the <b>debug</b> level,
|
|
if they are caught at all by internal code.
|
|
<br/>
|
|
For higher level frameworks and middleware components,
|
|
these exceptions should be caught immediatly prior to crossing
|
|
the API/SPI interface back to user code-space,
|
|
logged with full stack trace at <b>info</b> level,
|
|
and rethrown.
|
|
The assures that the log contains a record of the root cause for
|
|
future analysis <i>in the event that the exception is not caught and resolved
|
|
as expected by the user's code</i>.
|
|
<br/>
|
|
</li>
|
|
<li>
|
|
<b>External Boundaries - Unexpected Exceptions</b>.
|
|
This classification includes exceptions such as <code>NullPointerException</code>
|
|
that cross API/SPI boundaries, and are exposed to the user of a component/toolkit.
|
|
These are runtime exceptions/error that are NOT
|
|
listed in the 'throws' clause of a method signature.
|
|
<br/>
|
|
Appropriate handling of these exceptions depends upon the type
|
|
of code you are developing.
|
|
APIs for utility functions and tools should log these at the <b>debug</b> level,
|
|
if they are caught at all.
|
|
<br/>
|
|
For higher level frameworks and middleware components,
|
|
these exceptions should be caught immediately prior to crossing
|
|
the API/SPI interface back to user code-space,
|
|
logged with full stack trace at <b>info</b> level,
|
|
and rethrown/wrapped as <code><i>Component</i>InternalError</code>.
|
|
This ensures that the log contains a record of the root cause for
|
|
future analysis <i>in the event that the exception is not caught and
|
|
logged/reported as expected by the user's code</i>.
|
|
</li>
|
|
<li>
|
|
<b>Internal Boundaries</b>.
|
|
Exceptions that occur internally and are resolved internally.
|
|
These should be logged when caught as <b>debug</b> or <b>info</b> messages,
|
|
at the programmer's discretion.
|
|
</li>
|
|
<li>
|
|
<b>Significant Internal Boundaries</b>.
|
|
This typically only applies to middleware components that span networks or runtime processes.
|
|
Exceptions that cross over significant internal component boundaries such as networks
|
|
should be logged when caught as <b>info</b> messages.
|
|
Do not assume that such a (process/network) boundary will deliver exceptions to the 'other side'.
|
|
</li>
|
|
</ul>
|
|
</subsection>
|
|
<subsection name='When Info Level Instead of Debug?'>
|
|
<p>
|
|
You want to have exception/problem information available for
|
|
first-pass problem determination in a production level
|
|
enterprise application without turning on <b>debug</b>
|
|
as a default log level. There is simply too much information
|
|
in <b>debug</b> to be appropriate for day-to-day operations.
|
|
</p>
|
|
</subsection>
|
|
<subsection name='More Control of Enterprise Exception Logging'>
|
|
<p>
|
|
If more control is desired for the level of detail of these
|
|
'enterprise' exceptions, then consider creating a special
|
|
logger just for these exceptions:
|
|
</p>
|
|
<ul>
|
|
<source>
|
|
Log log = LogFactory.getLog("org.apache.<i>component</i>.enterprise");
|
|
</source>
|
|
</ul>
|
|
<p>
|
|
This allows the 'enterprise' level information to be turned on/off explicitly
|
|
by most logger implementations.
|
|
</p>
|
|
</subsection>
|
|
<subsection name='National Language Support And Internationalization'>
|
|
<p>
|
|
NLS internationalization involves looking up messages from
|
|
a message file by a message key, and using that message for logging.
|
|
There are various tools in Java, and provided by other components,
|
|
for working with NLS messages.
|
|
</p>
|
|
<p>
|
|
NLS enabled components are particularly appreciated
|
|
(that's an open-source-correct term for 'required by corporate end-users' :-)
|
|
for <strong>tooling</strong> and <strong>middleware</strong> components.
|
|
</p>
|
|
<p>
|
|
NLS internationalization SHOULD be strongly considered for used for
|
|
<b>fatal</b>, <b>error</b>, <b>warn</b>, and <b>info</b> messages.
|
|
It is generally considered optional for <b>debug</b> and <b>trace</b> messages.
|
|
</p>
|
|
<p>
|
|
Perhaps more direct support for internationalizing log messages
|
|
can be introduced in a future or alternate version of the <code>Log</code> interface.
|
|
</p>
|
|
</subsection>
|
|
<subsection name="Classloader and Memory Management">
|
|
<p>
|
|
The <code>LogFactory</code> discovery process (see
|
|
<a href='#Configuration'>Configuration</a> above) is a fairly expensive
|
|
operation, so JCL certainly should not perform it each time user code
|
|
invokes:
|
|
</p>
|
|
<source>LogFactory.getLog()</source>
|
|
<p>
|
|
Instead JCL caches the
|
|
<code>LogFactory</code> implementation created as a result of the discovery
|
|
process and uses the cached factory to return <code>Log</code> objects.
|
|
Since in J2EE and similar multi-classloader environments, the result of the
|
|
discovery process can vary depending on the thread context classloader
|
|
(e.g. one webapp in a web container may be configured to use Log4j and
|
|
another to use JDK 1.4 logging), JCL internally caches the
|
|
<code>LogFactory</code> instances in a static hashtable, keyed by classloader.
|
|
</p>
|
|
<p>
|
|
While this approach is efficient, it can lead to memory leaks if container
|
|
implementors are not careful to call
|
|
</p>
|
|
<source>LogFactory.release()</source>
|
|
<p>
|
|
whenever a classloader that has utilized JCL is undeployed. If
|
|
<code>release()</code> is not called, a reference to the undeployed
|
|
classloader (and thus to all the classes loaded by it) will be
|
|
held in <code>LogFactory</code>'s static hashtable.
|
|
</p>
|
|
<p>
|
|
Beginning with JCL 1.1, <code>LogFactory</code> caches factory implementations in a
|
|
"WeakHashtable". This class is similar to <code>java.util.WeakHashMap</code> in
|
|
that it holds a <code>WeakReference</code> to each key (but a strong reference
|
|
to each value), thus allowing classloaders to be GC'd even if
|
|
<code>LogFactory.release()</code> is never invoked.
|
|
</p>
|
|
<p>
|
|
Because <code>WeakHashtable</code> depends on JDK 1.3+ features, it is dynamically
|
|
loaded depending on the JVM version; when commons-logging is run on java versions
|
|
prior to 1.3 the code defaults to a standard Hashtable instead.
|
|
</p>
|
|
<p>
|
|
If a custom LogFactory implementation is used, however, then a
|
|
<code>WeakHashtable</code> alone can be insufficent to allow garbage collection
|
|
of a classloader without a call to <code>release</code>. If the abstract class
|
|
<code>LogFactory</code> is loaded by a parent classloader and a concrete
|
|
subclass implementation of <code>LogFactory</code> is loaded by a child
|
|
classloader, the WeakHashtable's key is a weak reference to the TCCL (child
|
|
classloader), but the value is a strong reference to the LogFactory instance,
|
|
which in turn contains a strong reference to its class and thus loading
|
|
classloader - the child classloader. This chain of strong references prevents
|
|
the child loader from being garbage collected.
|
|
</p>
|
|
<p>
|
|
If use of a custom <code>LogFactory</code> subclass is desired, ensuring that
|
|
the custom subclass is loaded by the same classloader as <code>LogFactory</code>
|
|
will prevent problems. In normal deployments, the standard implementations
|
|
of <code>LogFactory</code> found in package <code>org.apache.commons.logging.impl</code>
|
|
will be loaded by the same classloader that loads <code>LogFactory</code>
|
|
itself, so use of the standard <code>LogFactory</code> implementation
|
|
should not pose problems. Alternatively, use the provided ServletContextCleaner
|
|
to ensure this reference is explicitly released on webapp unload.
|
|
</p>
|
|
</subsection>
|
|
</section>
|
|
<section name='Extending Commons Logging'>
|
|
<p>
|
|
JCL is designed to encourage extensions to be created that add functionality.
|
|
Typically, extensions to JCL fall into two categories:
|
|
</p>
|
|
<ul>
|
|
<li>new <code>Log</code> implementations that provide new bridges to logging systems</li>
|
|
<li>
|
|
new <code>LogFactory</code> implementations that provide alternative discovery strategies
|
|
</li>
|
|
</ul>
|
|
<subsection name='Contract'>
|
|
<p>
|
|
When creating new implementations for <code>Log</code> and <code>LogFactory</code>,
|
|
it is important to understand the implied contract between the factory
|
|
and the log implementations:
|
|
<ul>
|
|
<li><b>Life cycle</b>
|
|
<blockquote>
|
|
The JCL LogFactory implementation must assume responsibility for
|
|
either connecting/disconnecting to a logging toolkit,
|
|
or instantiating/initializing/destroying a logging toolkit.
|
|
</blockquote>
|
|
</li>
|
|
<li><b>Exception handling</b>
|
|
<blockquote>
|
|
The JCL Log interface doesn't specify any exceptions to be handled,
|
|
the implementation must catch any exceptions.
|
|
</blockquote>
|
|
</li>
|
|
<li><b>Multiple threads</b>
|
|
<blockquote>
|
|
The JCL Log and LogFactory implementations must ensure
|
|
that any synchronization required by the logging toolkit
|
|
is met.
|
|
</blockquote>
|
|
</li>
|
|
</ul>
|
|
</p>
|
|
</subsection>
|
|
<subsection name='Creating a Log Implementation'>
|
|
<p>
|
|
The minimum requirement to integrate with another logger
|
|
is to provide an implementation of the
|
|
<code>org.apache.commons.logging.Log</code> interface.
|
|
In addition, an implementation of the
|
|
<code>org.apache.commons.logging.LogFactory</code> interface
|
|
can be provided to meet
|
|
specific requirements for connecting to, or instantiating, a logger.
|
|
</p>
|
|
<p>
|
|
The default <code>LogFactory</code> provided by JCL
|
|
can be configured to instantiate a specific implementation of the
|
|
<code>org.apache.commons.logging.Log</code> interface
|
|
by setting the property of the same name (<code>org.apache.commons.logging.Log</code>).
|
|
This property can be specified as a system property,
|
|
or in the <code>commons-logging.properties</code> file,
|
|
which must exist in the CLASSPATH.
|
|
</p>
|
|
</subsection>
|
|
<subsection name='Creating A LogFactory Implementation'>
|
|
<p>
|
|
If desired, the default implementation of the
|
|
<code>org.apache.commons.logging.LogFactory</code>
|
|
interface can be overridden,
|
|
allowing the JDK 1.3 Service Provider discovery process
|
|
to locate and create a LogFactory specific to the needs of the application.
|
|
Review the Javadoc for the <code>LogFactoryImpl.java</code>
|
|
for details.
|
|
</p>
|
|
</subsection>
|
|
</section>
|
|
<section name='A Quick Guide To Simple Log'>
|
|
<p>
|
|
JCL is distributed with a very simple <code>Log</code> implementation named
|
|
<code>org.apache.commons.logging.impl.SimpleLog</code>. This is intended to be a minimal
|
|
implementation and those requiring a fully functional open source logging system are
|
|
directed to <a href='http://logging.apache.org/log4j'>Log4J</a>.
|
|
</p>
|
|
<p>
|
|
<code>SimpleLog</code> sends all (enabled) log messages,
|
|
for all defined loggers, to <code>System.err</code>. The following system properties
|
|
are supported to configure the behavior of this logger:</p>
|
|
<ul>
|
|
<li><strong>org.apache.commons.logging.simplelog.defaultlog</strong> -
|
|
Default logging detail level for all instances of SimpleLog.
|
|
Must be one of:
|
|
<ul>
|
|
<li><code>trace</code></li>
|
|
<li><code>debug</code></li>
|
|
<li><code>info</code></li>
|
|
<li><code>warn</code></li>
|
|
<li><code>error</code></li>
|
|
<li><code>fatal</code></li>
|
|
</ul>
|
|
If not specified, defaults to <code>info</code>. </li>
|
|
<li><strong>org.apache.commons.logging.simplelog.log.xxxxx</strong> -
|
|
Logging detail level for a SimpleLog instance named "xxxxx".
|
|
Must be one of:
|
|
<ul>
|
|
<li><code>trace</code></li>
|
|
<li><code>debug</code></li>
|
|
<li><code>info</code></li>
|
|
<li><code>warn</code></li>
|
|
<li><code>error</code></li>
|
|
<li><code>fatal</code></li>
|
|
</ul>
|
|
If not specified, the default logging detail level is used.</li>
|
|
<li><strong>org.apache.commons.logging.simplelog.showlogname</strong> -
|
|
Set to <code>true</code> if you want the <code>Log</code> instance name to be
|
|
included in output messages. Defaults to <code>false</code>.</li>
|
|
<li><strong>org.apache.commons.logging.simplelog.showShortLogname</strong> -
|
|
Set to <code>true</code> if you want the last component of the name to be
|
|
included in output messages. Defaults to <code>true</code>.</li>
|
|
<li><strong>org.apache.commons.logging.simplelog.showdatetime</strong> -
|
|
Set to <code>true</code> if you want the current date and time
|
|
to be included in output messages. Default is <code>false</code>.</li>
|
|
<li><strong>org.apache.commons.logging.simplelog.dateTimeFormat</strong> -
|
|
The date and time format to be used in the output messages.
|
|
The pattern describing the date and time format is the same that is
|
|
used in <code>java.text.SimpleDateFormat</code>. If the format is not
|
|
specified or is invalid, the default format is used.
|
|
The default format is <code>yyyy/MM/dd HH:mm:ss:SSS zzz</code>.</li>
|
|
</ul>
|
|
|
|
<p>
|
|
In addition to looking for system properties with the names specified
|
|
above, this implementation also checks for a class loader resource named
|
|
<code>"simplelog.properties"</code>, and includes any matching definitions
|
|
from this resource (if it exists).
|
|
</p>
|
|
</section>
|
|
<section name='Frequently Asked Questions'>
|
|
<p>
|
|
See the <a href="http://wiki.apache.org/commons/Logging/FrequentlyAskedQuestions">FAQ document</a>
|
|
on the commons-logging wiki site
|
|
</p>
|
|
</section>
|
|
|
|
</body>
|
|
</document>
|