* Add updated LICENSE.txt and new NOTICE.txt files. * Add license header to currently unlicensed text files (html, xml, properties). git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@139009 13f79535-47bb-0310-9956-ffa450edef68
518 lines
20 KiB
HTML
518 lines
20 KiB
HTML
<!--
|
|
|
|
Copyright 2001-2004 The Apache Software Foundation.
|
|
|
|
Licensed 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.
|
|
|
|
-->
|
|
|
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<title>Jakarta Commons Logging Users Guide</title>
|
|
<!-- saved from url=(0022)http://internet.e-mail -->
|
|
<style type="text/css">
|
|
<!--
|
|
.example { background:#ccccff }
|
|
.xml { background:#eeeeee }
|
|
body { font-family: Verdana, Arial, Helvetica, sans-serif; margin-left: 40px}
|
|
h2 { text-decoration: underline; background-color: #DCE1FF; background-position: left; margin-left: -30px}
|
|
h3 { margin-left: -10px}
|
|
h1 { margin-left: -30px}
|
|
-->
|
|
</style>
|
|
</head>
|
|
<body text="#000000" bgcolor="#FFFFFF">
|
|
|
|
<h1>
|
|
Users Guide : Jakarta Commons Logging</h1>
|
|
<i>1.0 Version</i>
|
|
<h3>
|
|
Table of Contents</h3>
|
|
<a href="#Introduction">Introduction</a>
|
|
<br><a href="#Users">Users Quick Start</a>
|
|
<br><a href="#Developers">Developers</a>
|
|
<br> <a href="#Best Practices">Best Practices</a>
|
|
<br><a href="#Integration">Integration</a>
|
|
<br> <a href="#Mechanism">Mechanism</a>
|
|
<br> <a href="#Configuring the Logger Implementation">Configuring the Logger Implementation</a>
|
|
<br><a href="#FAQ">Frequently Asked Questions</a>
|
|
<br> <a href="#Thread Safety">Is JCL Thread Safe?</a>
|
|
|
|
<h2>
|
|
<a NAME="Introduction"></a>Introduction</h2>
|
|
|
|
<p>The Jakarta Commons Logging (JCL) provides a Log interface that
|
|
is intended to be both light-weight and independent of numerous logging toolkits.
|
|
It provides the middleware/tooling developer a simple
|
|
logging abstraction, that allows the user (application developer) to plug in
|
|
a specific logging implementation.
|
|
</p>
|
|
|
|
<p>Familiarity with high-level details of various Logging implementations is presumed.
|
|
</p>
|
|
|
|
<p>The Jakarta Commons Logging provides a Log interface with thin-wrapper implementations for
|
|
other logging tools, including
|
|
<a href="http://jakarta.apache.org/log4j/docs/index.html">Log4J</a>,
|
|
<a href="http://jakarta.apache.org/avalon/logkit/index.html">Avalon LogKit</a>,
|
|
and
|
|
<a>JDK 1.4</a>.
|
|
The interface maps closely to Log4J and LogKit.
|
|
</p>
|
|
|
|
<h2><a NAME="Users"></a>Users Quick Start</h2>
|
|
<p>
|
|
As far as possible, <em>Commons-Logging</em> tries to be as unobtrusive as possible.
|
|
In most cases, including the (full) <code>commons-logging.jar</code> in the classpath
|
|
should result in <em>Commons-Logging</em> 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>
|
|
<h3>Configuration</h3>
|
|
<p>
|
|
There are two base abstractions used by <em>Commons-Logging</em>: <code>Log</code>
|
|
(the basic logger) and <code>LogFactory</code> (which knows how to create <code>Log</code>
|
|
instances). Using <code>LogFactory</code> implementations other than the default is a
|
|
subject for advanced users only, so let's concentrate on configuring the default
|
|
implementation.
|
|
</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):
|
|
|
|
<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).</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://jakarta.apache.org/commons/logging/api/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://jakarta.apache.org/commons/logging/api/org/apache/commons/logging/impl/Jdk14Logger.html">Jdk14Logger</a>).</li>
|
|
<li>Fall back to the default simple logging wrapper
|
|
(<a href="http://jakarta.apache.org/commons/logging/api/org/apache/commons/logging/impl/SimpleLog.html">SimpleLog</a>).</li>
|
|
</ol>
|
|
|
|
Consult the <em>Commons-Logging</em> 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>
|
|
|
|
<h2><a NAME="Developers"></a>Developers</h2>
|
|
|
|
<p>
|
|
To use the JCL SPI from a Java class,
|
|
include the following import statements:
|
|
<ul>
|
|
<code>
|
|
import org.apache.commons.logging.Log;
|
|
<br>
|
|
import org.apache.commons.logging.LogFactory;
|
|
<br>
|
|
</code>
|
|
</ul>
|
|
Note that some components using commons-logging 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:
|
|
<ul>
|
|
<code>
|
|
public class CLASS
|
|
<br>{
|
|
<br> private static Log log = LogFactory.getLog(CLASS.class);
|
|
<br> ...
|
|
<br>
|
|
</code>
|
|
</ul>
|
|
<p>
|
|
Messages are logged to a <i>logger</i>, such as <code>log</code>
|
|
by invoking a method corresponding to <i>priority</i>.
|
|
The <code>org.apache.commons.logging.Log</code> interface defines the
|
|
following methods for use
|
|
in writing log/trace messages to the log:
|
|
<ul>
|
|
<code>
|
|
<br>log.fatal(Object message);
|
|
<br>log.fatal(Object message, Throwable t);
|
|
<br>log.error(Object message);
|
|
<br>log.error(Object message, Throwable t);
|
|
<br>log.warn(Object message);
|
|
<br>log.warn(Object message, Throwable t);
|
|
<br>log.info(Object message);
|
|
<br>log.info(Object message, Throwable t);
|
|
<br>log.debug(Object message);
|
|
<br>log.debug(Object message, Throwable t);
|
|
<br>log.trace(Object message);
|
|
<br>log.trace(Object message, Throwable t);
|
|
</code>
|
|
</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>
|
|
<code>
|
|
log.isFatalEnabled();
|
|
<br>log.isErrorEnabled();
|
|
<br>log.isWarnEnabled();
|
|
<br>log.isInfoEnabled();
|
|
<br>log.isDebugEnabled();
|
|
<br>log.isTraceEnabled();
|
|
</code>
|
|
</ul>
|
|
|
|
|
|
<h3><a NAME="Best Practices">Best Practices</a></h3>
|
|
<p>Best practices for programming/planning 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>
|
|
|
|
<h4>General - Code Guards</h4>
|
|
<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 (i.e. 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>
|
|
|
|
<h4>General - Message Priorities/Levels</h4>
|
|
It is important to ensure that log message are
|
|
appropriate in content and severity.
|
|
The following guidelines are suggested:</a>
|
|
<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="#Internationalization">Internationalization</a>.
|
|
</li>
|
|
<br>
|
|
<li><b>error</b> - Other runtime errors or unexpected conditions.
|
|
Expect these to be immediately visible on a status console.
|
|
See also <a HREF="#Internationalization">Internationalization</a>.
|
|
</li>
|
|
<br>
|
|
<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="#Internationalization">Internationalization</a>.
|
|
</li>
|
|
<br>
|
|
<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="#Internationalization">Internationalization</a>.
|
|
</li>
|
|
<br>
|
|
<li><b>debug</b> - detailed information on flow of through the system.
|
|
Expect these to be written to logs only.
|
|
</li>
|
|
<br>
|
|
<li><b>trace</b> - more detailed information.
|
|
Expect these to be written to logs only.
|
|
</li>
|
|
</ul>
|
|
|
|
<h4>General - Default Message Priority/Level</h4>
|
|
<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>
|
|
|
|
<h4>Enterprise - Logging Exceptions</h4>
|
|
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 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:
|
|
<ul>
|
|
<li><p><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.
|
|
</p>
|
|
<p>
|
|
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.
|
|
</p>
|
|
<p>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>.
|
|
</p>
|
|
</li>
|
|
<li><p><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.
|
|
</p>
|
|
<p>
|
|
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.
|
|
</p>
|
|
<p>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/wrapped as <code><i>Component</i>InternalError</code>.
|
|
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
|
|
logged/reported as expected by the user's code</i>.
|
|
</p></li>
|
|
<li><p><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.
|
|
</p></li>
|
|
<li><p><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.
|
|
These 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'.
|
|
</p></li>
|
|
</ul>
|
|
|
|
<h5>Why info level instead of debug?</h5>
|
|
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.
|
|
|
|
<h5>More Control of Enterprise Exception Logging</h5>
|
|
<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:
|
|
<ul>
|
|
<code>
|
|
Log log = LogFactory.getLog("org.apache.<i>component</i>.enterprise");
|
|
</code>
|
|
</ul>
|
|
This allows the 'enterprise' level information to be turned on/off explicitly
|
|
by most logger implementations.
|
|
|
|
</p>
|
|
|
|
<a NAME="Internationalization"></a>
|
|
<h4>Enterprise - National Language Support - Internationalization</h4>
|
|
<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
|
|
(thats 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>
|
|
|
|
<h2><a NAME="Integration"></a>Integration</h2>
|
|
|
|
<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>
|
|
|
|
<ul>
|
|
<li><h4>org.apache.commons.logging.Log</h4></li>
|
|
<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>
|
|
|
|
<h4>Default logger if not plugged</h4>
|
|
<p>
|
|
The Jakarta Commons Logging SPI uses the
|
|
implementation of the <code>org.apache.commons.logging.Log</code>
|
|
interface specified by the system property
|
|
<code>org.apache.commons.logging.Log</code>.
|
|
If the property is not specified or the class is not available then the JCL
|
|
provides access to a default logging toolkit by searching the CLASSPATH
|
|
for the following toolkits, in order of preference:
|
|
<ul>
|
|
<li><a href="http://jakarta.apache.org/log4j/docs/index.html">Log4J</a></li>
|
|
<li>JDK 1.4</li>
|
|
<li>JCL SimpleLog</li>
|
|
</ul>
|
|
</p>
|
|
|
|
<li><h4>org.apache.commons.logging.LogFactory</h4></li>
|
|
<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>
|
|
</ul>
|
|
|
|
<h3><a NAME="Mechanism">Mechanism</a></h3>
|
|
<ul>
|
|
<li><h5>Life cycle</h5></li>
|
|
The JCL LogFactory implementation must assume responsibility for
|
|
either connecting/disconnecting to a logging toolkit,
|
|
or instantiating/initializing/destroying a logging toolkit.
|
|
<br>
|
|
<li><h5>Exception handling</h5></li>
|
|
The JCL Log interface doesn't specify any exceptions to be handled,
|
|
the implementation must catch any exceptions.
|
|
<br>
|
|
<li><h5>Multiple threads</h5></li>
|
|
The JCL Log and LogFactory implementations must ensure
|
|
that any synchronization required by the logging toolkit
|
|
is met.
|
|
</ul>
|
|
|
|
<h3><a NAME="Configuring the Logger Implementation">Configuring the Logger Implementation</a></h3>
|
|
The Jakarta Commons Logging (JCL) SPI
|
|
can be configured to use different logging toolkits.
|
|
<p>
|
|
Configuration of the behavior of the JCL ultimately depends upon the
|
|
logging toolkit being used.
|
|
The JCL SPI uses
|
|
<a href="http://jakarta.apache.org/log4j/docs/index.html">Log4J</a>
|
|
by default if it is available (in the CLASSPATH).
|
|
<h4>Log4J</h4>
|
|
As
|
|
<a href="http://jakarta.apache.org/log4j/docs/index.html">Log4J</a>
|
|
is the default logger,
|
|
a <i>few</i> details are presented herein to get the developer/integrator going.
|
|
<p>
|
|
Configure Log4J using system properties and/or a properties file:
|
|
<ul>
|
|
<li><h5>log4j.configuration=<i>log4j.properties</i></h5></li>
|
|
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>.
|
|
|
|
<br>
|
|
<li><h5>log4j.rootCategory=<i>priority</i> [, <i>appender</i>]*</h5></li>
|
|
Set the default (root) logger priority.
|
|
|
|
<br>
|
|
<li><h5>log4j.logger.<i>logger.name</i>=<i>priority</i></h5></li>
|
|
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>.
|
|
<p>
|
|
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 Jakarta projects.
|
|
<br>
|
|
<li><h5>log4j.appender.<i>appender</i>.Threshold=<i>priority</i></h5></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.
|
|
<p>
|
|
For example: one can capture DEBUG (and higher) level information in a logfile,
|
|
while limiting console output to INFO (and higher).
|
|
</ul>
|
|
|
|
<h2><a NAME="FAQ">Frequently Asked Questions</a></h2>
|
|
|
|
<h3><a NAME="Thread Safety">Is JCL Thread Safe?</a></h3>
|
|
|
|
<p> JCL doesn't (and cannot) impose any requirement on thread safety on the underlying implementation and thus its SPI contract doesn't guarantee thread safety. However, JCL can be safely used a multi-threaded environment as long as the underlying implementation is thread-safe.</p>
|
|
|
|
<p>It would be very unusual for a logging system to be thread unsafe. Certainly, JCL is thread safe when used with the distributed Log implementations.</p>
|
|
|
|
</body>
|
|
</html>
|