| <!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="#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="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> |