| <?xml version="1.0"?> |
| |
| <!-- |
| |
| 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. |
| |
| --> |
| |
| <document> |
| |
| <properties> |
| <title>Users Guide : Jakarta Commons Logging</title> |
| <author email="commons-dev@jakarta.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></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 Jakarta 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> |
| <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 in each file, 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://jakarta.apache.org/commons/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://jakarta.apache.org/commons/logging/apidocs/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/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 Jakarta 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'> |
| <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> |
| <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> |
| </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/jakarta-commons/Logging/FrequentlyAskedQuestions">FAQ document</a> |
| on the commons-logging wiki site |
| </p> |
| </section> |
| |
| </body> |
| </document> |