| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
| <html xmlns="http://www.w3.org/1999/xhtml"> |
| <head> |
| <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /> |
| <title>Log4j Bridge</title> |
| <link rel="stylesheet" type="text/css" media="screen" href="css/site.css" /> |
| <link rel="stylesheet" type="text/css" media="print" href="css/print.css" /> |
| |
| </head> |
| |
| <body onload="decorate();"> |
| <script type="text/javascript">prefix='';</script> |
| |
| <script type="text/javascript" src="templates/header.js"></script> |
| <script type="text/javascript" src="js/jquery-min.js"></script> |
| <script type="text/javascript" src="js/decorator.js"></script> |
| |
| <div id="left"> |
| <script src="templates/left.js" type="text/javascript"></script> |
| </div> |
| <div id="content"> |
| |
| |
| <h2>Bridging legacy APIs</h2> |
| |
| <p>Often, some of the components you depend on rely on a logging |
| API other than SLF4J. You may also assume that these components |
| will not switch to SLF4J in the immediate future. To deal with |
| such circumstances, SLF4J ships with several bridging modules |
| which redirect calls made to log4j, JCL and java.util.logging APIs |
| to behave as if they were made to the SLF4J API instead. The |
| figure below illustrates the idea. |
| </p> |
| |
| <p>Please note that for source code under your control, you really |
| should use the <a href="migrator.html">slf4j-migrator</a>. The |
| binary-based solutions described in this page are appropriate for |
| software beyond your control. |
| </p> |
| |
| <p></p> |
| <p></p> |
| |
| |
| <p><a href="images/legacy.png"> |
| <img src="images/legacy.png" alt="click to enlarge" width="800"/> |
| </a></p> |
| |
| <p> |
| </p> |
| |
| <h2 class="doAnchor" name="jcl-over-slf4j">Gradual migration to |
| SLF4J from Jakarta Commons Logging (JCL)</h2> |
| |
| <h4 class="doAnchor" name="jclOverSLF4J"><em>jcl-over-slf4j.jar</em></h4> |
| |
| <p>To ease migration to SLF4J from JCL, SLF4J distributions |
| include the jar file <em>jcl-over-slf4j.jar</em>. This jar file is |
| intended as a drop-in replacement for JCL version 1.1.1. It |
| implements the public API of JCL but using SLF4J underneath, hence |
| the name "JCL over SLF4J." |
| </p> |
| |
| <p>Our JCL over SLF4J implementation will allow you to migrate to |
| SLF4J gradually, especially if some of the libraries your software |
| depends on continue to use JCL for the foreseeable future. You can |
| immediately enjoy the benefits of SLF4J's reliability and preserve |
| backward compatibility at the same time. Just replace |
| <em>commons-logging.jar</em> with |
| <em>jcl-over-slf4j.jar</em>. Subsequently, the selection of the |
| underlying logging framework will be done by SLF4J instead of JCL |
| <a href="http://articles.qos.ch/classloader.html">but without the |
| class loader headaches plaguing JCL</a>. The underlying logging |
| framework can be any of the frameworks supported by SLF4J. Often |
| times, replacing <em>commons-logging.jar</em> with |
| <em>jcl-over-slf4j.jar</em> will immediately and permanently solve |
| class loader issues related to commons logging. |
| </p> |
| |
| <h3 class="doAnchor" name="slf4jJCL"><em>slf4j-jcl.jar</em></h3> |
| |
| <p>Some of our users after having switched to SLF4J API realize that |
| in some contexts the use of JCL is mandatory and their use of SLF4J |
| can be a problem. For this uncommon but important case, SLF4J offers |
| a JCL binding, found in the file <em>slf4j-jcl.jar</em>. The JCL |
| binding will delegate all logging calls made through SLF4J API to |
| JCL. Thus, if for some reason an existing application <em>must</em> |
| use JCL, your part of that application can still code against the |
| SLF4J API in a manner transparent to the larger application |
| environment. Your choice of SLF4J API will be invisible to the rest |
| of the application which can continue to use JCL. |
| </p> |
| |
| <h3 class="doAnchor" |
| name="jclRecursion"><em>jcl-over-slf4j.jar</em> should not be |
| confused with <em>slf4j-jcl.jar</em></h3> |
| |
| |
| <p>JCL-over-SLF4J, i.e. <em>jcl-over-slf4j.jar</em>, comes in handy |
| in situations where JCL needs to be supported for backward |
| compatibility reasons. It can be used to fix problems associated |
| with JCL, without necessarily adopting the SLF4J API, a decision |
| which can be deferred to a later time. |
| </p> |
| |
| <p>On the other hand, <em>slf4j-jcl.jar</em> is useful |
| <strong>after</strong> you have already adopted the SLF4J API for |
| your component which needs to be embedded in a larger application |
| environment where JCL is a formal requirement. Your software |
| component can still use SLF4J API without disrupting the larger |
| application. Indeed, <em>slf4j-jcl.jar</em> will delegate all |
| logging decisions to JCL so that the dependency on SLF4J API by your |
| component will be transparent to the larger whole. |
| </p> |
| |
| <p>Please note that <em>jcl-over-slf4j.jar</em> and |
| <em>slf4j-jcl.jar</em> cannot be deployed at the same time. The |
| former jar file will cause JCL to delegate the choice of the |
| logging system to SLF4J and the latter jar file will cause SLF4J |
| to delegate the choice of the logging system to JCL, resulting in |
| an <a href="codes.html#jclDelegationLoop">infinite loop</a>. |
| </p> |
| |
| |
| <h2 class="doAnchor" name="log4j-over-slf4j">log4j-over-slf4j</h2> |
| |
| <p>SLF4J ship with a module called <em>log4j-over-slf4j</em>. It |
| allows log4j users to migrate existing applications to SLF4J without |
| changing <em>a single line of code</em> but simply by replacing the |
| <em>log4j.jar</em> file with <em>log4j-over-slf4j.jar</em>, as |
| described below. |
| </p> |
| |
| <h4 class="doAnchor" name="losHow">How does it work?</h4> |
| |
| <p>The log4j-over-slf4j module contains replacements of most widely |
| used log4j classes, namely <code>org.apache.log4j.Category</code>, |
| <code>org.apache.log4j.Logger</code>, |
| <code>org.apache.log4j.Priority</code>, |
| <code>org.apache.log4j.Level</code>, |
| <code>org.apache.log4j.MDC</code>, and |
| <code>org.apache.log4j.BasicConfigurator</code>. These replacement |
| classes redirect all work to their corresponding SLF4J classes. |
| </p> |
| |
| <p>To use log4j-over-slf4j in your own application, the first step |
| is to locate and then to replace <em>log4j.jar</em> with |
| <em>log4j-over-slf4j.jar</em>. Note that you still need an SLF4J |
| binding and its dependencies for log4j-over-slf4j to work properly. |
| </p> |
| |
| <p>In most situations, replacing a jar file is all it takes in |
| order to migrate from log4j to SLF4J. |
| </p> |
| |
| <p>Note that as a result of this migration, log4j configuration |
| files will no longer be picked up. If you need to migrate your |
| log4j.properties file to logback, the <a |
| href="http://logback.qos.ch/translator/">log4j translator</a> might |
| be of help. For configuring logback, please refer to <a |
| href="http://logback.qos.ch/manual/index.html">its manual</a>. |
| </p> |
| |
| <h4 class="doAnchor" name="losFail">When does it not work?</h4> |
| |
| <p>The <em>log4j-over-slf4j</em> module will not work when the |
| application calls log4j components that are not present in the |
| bridge. For example, when application code directly references |
| log4j appenders, filters or the PropertyConfigurator, then |
| log4j-over-slf4j would be an insufficient replacement for |
| log4j. However, when log4j is configured through a configuration |
| file, be it <em>log4j.properties</em> or <em>log4j.xml</em>, the |
| log4j-over-slf4j module should just work fine. |
| </p> |
| |
| |
| |
| <h4 class="doAnchor" name="losOverhead">What about the |
| overhead?</h4> |
| |
| <p>There overhead of using log4j-over-slf4j instead of log4j |
| directly is relatively small. Given that log4j-over-slf4j |
| immediately delegates all work to SLF4J, the CPU overhead should be |
| negligible, in the order of a few <em>nanoseconds</em>. There is a |
| memory overhead corresponding to an entry in a hashmap per logger, |
| which should be usually acceptable even for very large applications |
| consisting of several thousand loggers. Moreover, if you choose |
| logback as your underlying logging system, and given that logback is |
| both much faster and more memory-efficient than log4j, the gains |
| made by using logback should compensate for the overhead of using |
| log4j-over-slf4j instead of log4j directly. |
| </p> |
| |
| <h4 class="doAnchor" name="log4jRecursion">log4j-over-slf4j.jar |
| and slf4j-log4j12.jar cannot be present simultaneously |
| </h4> |
| |
| <p>The presence of <em>slf4j-log4j12.jar</em>, that is the log4j |
| binding for SLF4J, will force all SLF4J calls to be delegated to |
| log4j. The presence of <em>log4j-over-slf4j.jar</em> will in turn |
| delegate all log4j API calls to their SLF4J equivalents. If both |
| are present simultaneously, slf4j calls will be delegated to |
| log4j, and log4j calls redirected to SLF4j, resulting in an <a |
| href="codes.html#log4jDelegationLoop">endless loop</a>. |
| </p> |
| |
| |
| |
| <h2 class="doAnchor" name="jul-to-slf4j">jul-to-slf4j bridge</h2> |
| |
| <p>The jul-to-slf4j module includes a java.util.logging (jul) |
| handler, namely <code>SLF4JBridgeHandler</code>, which routes all |
| incoming jul records to the SLF4j API. Please see <a |
| href="api/org/slf4j/bridge/SLF4JBridgeHandler.html">SLF4JBridgeHandler |
| javadocs</a> for usage instructions. |
| </p> |
| |
| <p><span class="label notice">Note on performance</span> Contrary |
| to other bridging modules, namely jcl-over-slf4j and |
| log4j-over-slf4j, which reimplement JCL and respectively log4j, |
| the jul-to-slf4j module does not reimplement the java.util.logging |
| because packages under the java.* namespace cannot be |
| replaced. Instead, jul-to-slf4j translates <a |
| href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/logging/LogRecord.html?is-external=true">LogRecord</a> |
| objects into their SLF4J equivalent. Please note this translation |
| process incurs the cost of constructing a <code>LogRecord</code> |
| instance regardless of whether the SLF4J logger is disabled for |
| the given level or nor. <b>Consequently, j.u.l. to SLF4J |
| translation can seriously increase the cost of disabled logging |
| statements (60 fold or 6000%) and measurably impact the |
| performance of enabled log statements (20% overall increase).</b> |
| As of logback version 0.9.25, it is possible to completely |
| eliminate the 60 fold translation overhead for disabled log |
| statements with the help of <a |
| href="http://logback.qos.ch/manual/configuration.html#LevelChangePropagator">LevelChangePropagator</a>. |
| </p> |
| |
| <p>If you are concerned about application performance, then use of |
| <code>SLF4JBridgeHandler</code> is appropriate only if any one of |
| the following two conditions is true: |
| </p> |
| <ol> |
| <li>few j.u.l. logging statements are in play </li> |
| <li><code>LevelChangePropagator</code> has been installed</li> |
| </ol> |
| |
| |
| <h4 class="doAnchor" name="julRecursion">jul-to-slf4j.jar and slf4j-jdk14.jar cannot be present |
| simultaneously |
| </h4> |
| |
| <p>The presence of slf4j-jdk14.jar, that is the jul binding for |
| SLF4J, will force SLF4J calls to be delegated to jul. On the other |
| hand, the presence of jul-to-slf4j.jar, plus the installation of |
| SLF4JBridgeHandler, by invoking "SLF4JBridgeHandler.install()" will |
| route jul records to SLF4J. Thus, if both jar are present |
| simultaneously (and SLF4JBridgeHandler is installed), slf4j calls |
| will be delegated to jul and jul records will be routed to SLF4J, |
| resulting in an endless loop. |
| </p> |
| |
| |
| <script src="templates/footer.js" type="text/javascript"></script> |
| </div> |
| </body> |
| </html> |