Move/rename "xdocs" directory to standard m2 "src/site/xdoc"
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/logging/trunk@933590 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
850
src/site/xdoc/guide.xml
Normal file
850
src/site/xdoc/guide.xml
Normal file
@@ -0,0 +1,850 @@
|
||||
<?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 (discover) your preferred logging system and you won't
|
||||
need to do any configuration of JCL 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>
|
||||
<p>
|
||||
When no particular logging library is specified then JCL will silently ignore any logging library
|
||||
that it finds but cannot initialise and continue to look for other alternatives. This is a deliberate
|
||||
design decision; no application should fail to run because a "guessed" logging library cannot be
|
||||
used. To ensure an exception is reported when a particular logging library cannot be used, use one
|
||||
of the available JCL configuration mechanisms to force that library to be selected (ie disable
|
||||
JCL's discovery process).
|
||||
</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>
|
||||
<p>
|
||||
JCL is NOT responsible for initialisation, configuration or shutdown of the underlying logging library.
|
||||
In many cases logging libraries will automatically initialise/configure themselves when first used, and
|
||||
need no explicit shutdown process. In these situations an application can simply use JCL and not depend
|
||||
directly on the API of the underlying logging system in any way. However if the logging library being used
|
||||
requires special initialisation, configuration or shutdown then some logging-library-specific code will
|
||||
be required in the application. JCL simply forwards logging method calls to the correct underlying
|
||||
implementation. When writing library code this issue is of course not relevant as the calling application
|
||||
is responsible for handling such issues.
|
||||
</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>
|
||||
Reference in New Issue
Block a user