You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2014/07/17 17:15:01 UTC

svn commit: r1611386 - in /logging/log4j/log4j2/trunk/src: changes/changes.xml site/site.xml site/xdoc/manual/customloglevels.xml

Author: rpopma
Date: Thu Jul 17 15:15:00 2014
New Revision: 1611386

URL: http://svn.apache.org/r1611386
Log:
LOG4J2-710 Added documentation for Custom Levels and Custom Logger Wrappers

Added:
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/customloglevels.xml   (with props)
Modified:
    logging/log4j/log4j2/trunk/src/changes/changes.xml
    logging/log4j/log4j2/trunk/src/site/site.xml

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1611386&r1=1611385&r2=1611386&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Thu Jul 17 15:15:00 2014
@@ -22,6 +22,9 @@
   </properties>
   <body>
     <release version="?" date="2014-mm-dd" description="?">
+      <action issue="LOG4J2-710" dev="popmarem" type="add">
+        Added documentation for Custom Levels and Custom Loggers.
+      </action>
       <action issue="LOG4J2-719" dev="popmarem" type="fix">
         Correctly handle NetworkOnMainThreadException thrown on Android during Log4j2 initialization.
       </action>

Modified: logging/log4j/log4j2/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/site.xml?rev=1611386&r1=1611385&r2=1611386&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/site.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/site.xml Thu Jul 17 15:15:00 2014
@@ -166,6 +166,13 @@
         <item name="ConfigurationFactory" href="/manual/custom.config#ConfigurationFactory"/>
         <item name="Manual" href="/manual/custom.config#AddingToCurrent"/>
       </item>
+
+      <item name="Custom Log Levels" href="/manual/customloglevels.html" collapse="true">
+        <item name="Adding or Replacing Levels" href="/manual/customloglevels.html#AddingOrReplacingLevels"/>
+        <item name="Custom Loggers" href="/manual/customloglevels.html#CustomLoggers"/>
+        <item name="Custom Logger Example" href="/manual/customloglevels.html#ExampleUsage"/>
+        <item name="Code Generation Tool" href="/manual/customloglevels.html#CodeGen"/>
+      </item>
     </menu>
 
     <menu name="Components" inherit="top" img="icon-cog">

Added: logging/log4j/log4j2/trunk/src/site/xdoc/manual/customloglevels.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/customloglevels.xml?rev=1611386&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/customloglevels.xml (added)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/customloglevels.xml Thu Jul 17 15:15:00 2014
@@ -0,0 +1,231 @@
+<?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 xmlns="http://maven.apache.org/XDOC/2.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
+    <properties>
+        <title>Custom Log Levels</title>
+        <author email="rpopma@apache.org">Remko Popma</author>
+    </properties>
+
+    <body>
+      <a name="top" />
+      <section name="Custom Log Levels">
+        <p>
+          Log4J 2 supports custom log levels. The <tt>Level.forName()</tt> method creates a new
+          level for the specified name. By calling the Logger.log() method and passing this
+          custom log level you can log messages at this level:
+        </p>
+            <pre class="prettyprint">
+final Logger logger = LogManager.getLogger();
+final Level VERBOSE = Level.forName("VERBOSE", 550);
+
+logger.log(VERBOSE, "a verbose message");
+logger.log(VERBOSE, "another message");</pre>
+        <p>When defining a custom log level, the <tt>intLevel</tt> parameter (550 in the example above) determines
+           where the custom level exists in relation to the standard levels built-in to Log4J 2.
+           For reference, the table below shows the <tt>intLevel</tt> of the built-in log levels.
+         </p>
+         <table style="width: 30%">
+          <caption align="top">Standard log levels built-in to Log4J</caption>
+          <tr>
+            <th>Standard Level</th>
+            <th>intLevel</th>
+          </tr>
+          <tr>
+            <td>OFF</td>
+            <td align="right">0</td>
+          </tr>
+          <tr>
+            <td>FATAL</td>
+            <td align="right">100</td>
+          </tr>
+          <tr>
+            <td>ERROR</td>
+            <td align="right">200</td>
+          </tr>
+          <tr>
+            <td>WARN</td>
+            <td align="right">300</td>
+          </tr>
+          <tr>
+            <td>INFO</td>
+            <td align="right">400</td>
+          </tr>
+          <tr>
+            <td>DEBUG</td>
+            <td align="right">500</td>
+          </tr>
+          <tr>
+            <td>TRACE</td>
+            <td align="right">600</td>
+          </tr>
+          <tr>
+            <td>ALL</td>
+            <td align="right"><tt>Integer.MAX_VALUE</tt></td>
+          </tr>
+        </table>          
+         
+          <a name="StandardLoggerInterface" />
+          <subsection name="Convenience Methods for the Built-in Log Levels">
+            <p>
+              The built-in log levels have a set of convenience methods on the Logger
+              interface that makes them easier to use. For example, the Logger interface
+              has fourteen <tt>debug()</tt> methods that support the DEBUG level:
+            </p>
+            <pre class="prettyprint">
+// convenience methods for the built-in DEBUG level
+debug(Marker, Message)
+debug(Marker, Message, Throwable)
+debug(Marker, Object)
+debug(Marker, Object, Throwable)
+debug(Marker, String)
+debug(Marker, String, Object...)
+debug(Marker, String, Throwable)
+debug(Message)
+debug(Message, Throwable)
+debug(Object)
+debug(Object, Throwable)
+debug(String)
+debug(String, Object...)
+debug(String, Throwable)</pre>
+            <p>
+              Similar methods exist for the other built-in levels.
+            </p>
+            <p>It would be nice to have the same ease of use with custom levels,
+               so that after declaring a custom VERBOSE level, we would be able to
+               use code like this:
+            </p>
+            <pre class="prettyprint">
+logger.verbose("a verbose message"); // no need to pass the VERBOSE level as a parameter
+logger.verbose("another message");</pre>
+          </subsection>
+          <a name="AddingOrReplacingLevels" />
+          <subsection name="Adding or Replacing Log Levels">
+            <p>In the above example, a convenience method was <em>added</em> to the Logger interface,
+               in addition to the existing trace(), debug(), info(), ... methods for the built-in log levels.
+            </p>
+            <p>There is another use case, Domain Specific Language loggers, where we want to <em>replace</em>
+               the existing trace(), debug(), info(), ... methods with all-custom methods.
+            </p>
+            <p>
+              For example, for medical devices we could have only <tt>critical()</tt>, <tt>warning()</tt>,
+              and <tt>advisory()</tt> methods. 
+              Another example could be a game that has only <tt>defcon1()</tt>, <tt>defcon2()</tt>,
+              and <tt>defcon3()</tt> levels.
+            </p>
+            <p>
+              If it were possible to hide existing log levels, users could customize the
+              Logger interface to match their requirements. Some people may not want to
+              have a FATAL or a TRACE level, for example. They would like to be able to
+              create a custom Logger that only has debug(), info(), warn() and error() methods.
+            </p>
+          </subsection>
+          <a name="CustomLoggers" />
+          <subsection name="Generating Source Code for a Custom Logger Wrapper">
+            <p>
+              Common Log4J usage is to get an instance of the <tt>Logger</tt> interface from the
+              <tt>LogManager</tt> and call the methods on this interface.
+              However, the custom log Levels are not known in advance, so Log4J cannot provide
+              an interface with convenience methods for these custom log Levels.
+            </p>
+            <p>
+              To solve this, Log4J ships with a tool that generates source code for a
+              Logger wrapper. The generated wrapper class has convenience methods for each
+              custom log level, making custom levels just as easy to use as the built-in levels.
+            </p>
+            <p>
+              There are two flavors of wrappers: ones that <em><b>extend</b></em> the Logger
+              API (adding methods to the built-in levels) and ones that <em><b>customize</b></em>
+              the Logger API (replacing the built-in methods).
+            </p>
+            <p>When generating the source code for a wrapper class, you need to specify:</p>
+            <ul>
+              <li>the fully qualified name of the class to generate
+              </li>
+              <li>the list of custom levels to support and their <tt>intLevel</tt> relative strength
+              </li>
+              <li>whether to extend <tt>Logger</tt> (and keep the existing built-in methods)
+                or have only methods for the custom log levels
+              </li>
+            </ul>
+            <p>You would then include the generated source code in the project
+              where you want to use custom log levels.</p>
+          </subsection>
+          <a name="ExampleUsage" />
+          <subsection name="Example Usage of a Generated Logger Wrapper">
+            <p>
+              Here is an example of how one would use a generated logger wrapper with
+              custom levels DIAG, NOTICE and VERBOSE:
+            </p>
+            <pre class="prettyprint linenums">
+// ExtLogger is a generated logger wrapper
+import com.mycompany.myproject.ExtLogger;
+
+public class MyService {
+    // instead of Logger logger = LogManager.getLogger(MyService.class):
+    private static final ExtLogger logger = ExtLogger.create(MyService.class);
+    
+    public void someMethod() {
+        // ...
+        logger.trace("the built-in TRACE level");
+        logger.verbose("a custom level: a VERBOSE message");
+        logger.debug("the built-in DEBUG level");
+        logger.notice("a custom level: a NOTICE message");
+        logger.info("the built-in INFO level");
+        logger.diag("a custom level: a DIAG message");
+        logger.warn("the built-in WARN level");
+        logger.error("the built-in ERROR level");
+        logger.fatal("the built-in FATAL level");
+        // ...
+    }
+    ...
+}</pre>
+          </subsection>
+          <a name="CodeGen" />
+          <subsection name="Generating Extended Loggers">
+            <p>
+              Use the following command to generate a logger wrapper that adds methods to the built-in ones:
+            </p>
+            <pre class="prettyprint">
+java org.apache.logging.log4j.core.tools.Generate$ExtendedLogger com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550 > ExtLogger.java</pre>
+            <p>
+              This will generate source code for a logger wrapper that has the convenience methods
+              for the built-in levels <em>as well as</em> the specified custom levels. The tool prints the
+              generated source code to the console,
+              so we added "&gt; <em>filename</em>" to redirect the output to a file.
+            </p>
+          </subsection>
+          <subsection name="Generating Custom Loggers">
+            <p>
+              Use the following command to generate a logger wrapper that hides the built-in levels and has only custom levels:
+            </p>
+            <pre class="prettyprint">
+java org.apache.logging.log4j.core.tools.Generate$CustomLogger com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 > MyLogger.java</pre>
+            <p>
+              This will generate source code for a logger wrapper that <em>only</em> has convenience
+              methods for the specified custom levels, <em>not</em> for the built-in levels.
+              The tool prints the generated source code to the console,
+              so we added "&gt; <em>filename</em>" to redirect the output to a file.
+            </p>
+          </subsection>
+      </section>
+
+    </body>
+</document>

Propchange: logging/log4j/log4j2/trunk/src/site/xdoc/manual/customloglevels.xml
------------------------------------------------------------------------------
    svn:eol-style = native