"Fossies" - the Fresh Open Source Software Archive

Member "apache-log4j-2.12.4-src/src/site/xdoc/manual/customloglevels.xml.vm" (20 Dec 2021, 16042 Bytes) of package /linux/misc/apache-log4j-2.12.4-src.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 <?xml version="1.0"?>
    2 <!--
    3     Licensed to the Apache Software Foundation (ASF) under one or more
    4     contributor license agreements.  See the NOTICE file distributed with
    5     this work for additional information regarding copyright ownership.
    6     The ASF licenses this file to You under the Apache License, Version 2.0
    7     (the "License"); you may not use this file except in compliance with
    8     the License.  You may obtain a copy of the License at
    9 
   10          http://www.apache.org/licenses/LICENSE-2.0
   11 
   12     Unless required by applicable law or agreed to in writing, software
   13     distributed under the License is distributed on an "AS IS" BASIS,
   14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15     See the License for the specific language governing permissions and
   16     limitations under the License.
   17 -->
   18 #set($dollar = '$')
   19 
   20 <document xmlns="http://maven.apache.org/XDOC/2.0"
   21           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   22           xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
   23     <properties>
   24         <title>Custom Log Levels</title>
   25         <author email="rpopma@apache.org">Remko Popma</author>
   26     </properties>
   27 
   28     <body>
   29       <a name="top" />
   30       <section name="Custom Log Levels">
   31         <a name="DefiningLevelsInCode" />
   32         <subsection name="Defining Custom Log Levels in Code">
   33         <p>
   34           Log4J 2 supports custom log levels. Custom log levels can be defined in code
   35           or in configuration. To define a custom log level in code, use the
   36           <tt>Level.forName()</tt> method. This method creates a new
   37           level for the specified name. After a log level is defined you can log
   38           messages at this level by calling the Logger.log() method and passing
   39           the custom log level:
   40         </p>
   41             <pre class="prettyprint">
   42 // This creates the "VERBOSE" level if it does not exist yet.
   43 final Level VERBOSE = Level.forName("VERBOSE", 550);
   44 
   45 final Logger logger = LogManager.getLogger();
   46 logger.log(VERBOSE, "a verbose message"); // use the custom VERBOSE level
   47 
   48 // Create and use a new custom level "DIAG".
   49 logger.log(Level.forName("DIAG", 350), "a diagnostic message");
   50 
   51 // Use (don't create) the "DIAG" custom level.
   52 // Only do this *after* the custom level is created!
   53 logger.log(Level.getLevel("DIAG"), "another diagnostic message");
   54 
   55 // Using an undefined level results in an error: Level.getLevel() returns null,
   56 // and logger.log(null, "message") throws an exception.
   57 logger.log(Level.getLevel("FORGOT_TO_DEFINE"), "some message"); // throws exception!</pre>
   58         <p>When defining a custom log level, the <tt>intLevel</tt> parameter (550 and 350 in the example above) determines
   59            where the custom level exists in relation to the standard levels built-in to Log4J 2.
   60            For reference, the table below shows the <tt>intLevel</tt> of the built-in log levels.
   61          </p>
   62          <table style="width: 30%">
   63           <caption align="top">Standard log levels built-in to Log4J</caption>
   64           <tr>
   65             <th>Standard Level</th>
   66             <th>intLevel</th>
   67           </tr>
   68           <tr>
   69             <td>OFF</td>
   70             <td align="right">0</td>
   71           </tr>
   72           <tr>
   73             <td>FATAL</td>
   74             <td align="right">100</td>
   75           </tr>
   76           <tr>
   77             <td>ERROR</td>
   78             <td align="right">200</td>
   79           </tr>
   80           <tr>
   81             <td>WARN</td>
   82             <td align="right">300</td>
   83           </tr>
   84           <tr>
   85             <td>INFO</td>
   86             <td align="right">400</td>
   87           </tr>
   88           <tr>
   89             <td>DEBUG</td>
   90             <td align="right">500</td>
   91           </tr>
   92           <tr>
   93             <td>TRACE</td>
   94             <td align="right">600</td>
   95           </tr>
   96           <tr>
   97             <td>ALL</td>
   98             <td align="right"><tt>Integer.MAX_VALUE</tt></td>
   99           </tr>
  100         </table>
  101         </subsection>
  102         <a name="DefiningLevelsInConfiguration" />
  103         <subsection name="Defining Custom Log Levels in Configuration">
  104           <p>
  105           Custom log levels can also be defined in configuration.
  106           This is convenient for using a custom level in a logger filter
  107           or an appender filter. Similar to defining log levels in code,
  108           a custom level must be defined first, before it can be used.
  109           If a logger or appender is configured with an undefined level,
  110           that logger or appender will be invalid and will not process any log events.
  111           </p>
  112           <p>
  113             The <b>CustomLevel</b> configuration element creates a custom level.
  114             Internally it calls the same <tt>Level.forName()</tt> method discussed above.
  115           </p>
  116           <table>
  117             <caption align="top">CustomLevel Parameters</caption>
  118             <tr>
  119               <th>Parameter Name</th>
  120               <th>Type</th>
  121               <th>Description</th>
  122             </tr>
  123             <tr>
  124               <td>name</td>
  125               <td>String</td>
  126               <td>The name of the custom level. Note that level names are case sensitive.
  127                 The convention is to use all upper-case names.</td>
  128             </tr>
  129             <tr>
  130               <td>intLevel</td>
  131               <td>integer</td>
  132               <td>Determines where the custom level exists in relation to the
  133                 standard levels built-in to Log4J 2 (see the table above).</td>
  134             </tr>
  135           </table>
  136           <p>
  137           The following example shows a configuration that defines some custom
  138           log levels and uses a custom log level to filter log events sent to the console.
  139           </p>
  140           <pre class="prettyprint linenums"><![CDATA[
  141 <?xml version="1.0" encoding="UTF-8"?>
  142 <Configuration status="WARN">
  143   <!-- Define custom levels before using them for filtering below. -->
  144   <CustomLevels>
  145     <CustomLevel name="DIAG" intLevel="350" />
  146     <CustomLevel name="NOTICE" intLevel="450" />
  147     <CustomLevel name="VERBOSE" intLevel="550" />
  148   </CustomLevels>
  149 
  150   <Appenders>
  151     <Console name="Console" target="SYSTEM_OUT">
  152       <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/>
  153     </Console>
  154     <File name="MyFile" fileName="logs/app.log">
  155       <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/>
  156     </File>
  157   </Appenders>
  158   <Loggers>
  159     <Root level="trace">
  160       <!-- Only events at DIAG level or more specific are sent to the console. -->
  161       <AppenderRef ref="Console" level="diag" />
  162       <AppenderRef ref="MyFile" level="trace" />
  163     </Root>
  164   </Loggers>
  165 </Configuration>]]></pre>
  166         </subsection>
  167           <a name="StandardLoggerInterface" />
  168           <subsection name="Convenience Methods for the Built-in Log Levels">
  169             <p>
  170               The built-in log levels have a set of convenience methods on the Logger
  171               interface that makes them easier to use. For example, the Logger interface
  172               has 24 <tt>debug()</tt> methods that support the DEBUG level:
  173             </p>
  174             <pre class="prettyprint">
  175 // convenience methods for the built-in DEBUG level
  176 debug(Marker, Message)
  177 debug(Marker, Message, Throwable)
  178 debug(Marker, Object)
  179 debug(Marker, Object, Throwable)
  180 debug(Marker, String)
  181 debug(Marker, String, Object...)
  182 debug(Marker, String, Throwable)
  183 debug(Message)
  184 debug(Message, Throwable)
  185 debug(Object)
  186 debug(Object, Throwable)
  187 debug(String)
  188 debug(String, Object...)
  189 debug(String, Throwable)
  190 // lambda support methods added in 2.4
  191 debug(Marker, MessageSupplier)
  192 debug(Marker, MessageSupplier, Throwable)
  193 debug(Marker, String, Supplier&lt;?&gt;...)
  194 debug(Marker, Supplier&lt;?&gt;)
  195 debug(Marker, Supplier&lt;?&gt;, Throwable)
  196 debug(MessageSupplier)
  197 debug(MessageSupplier, Throwable)
  198 debug(String, Supplier&lt;?&gt;...)
  199 debug(Supplier&lt;?&gt;)
  200 debug(Supplier&lt;?&gt;, Throwable)</pre>
  201             <p>
  202               Similar methods exist for the other built-in levels.
  203               Custom levels, in contrast, need to pass in the log level as an extra parameter.
  204             </p>
  205             <pre class="prettyprint">
  206 // need to pass the custom level as a parameter
  207 logger.log(VERBOSE, "a verbose message");
  208 logger.log(Level.forName("DIAG", 350), "another message");</pre>
  209             <p>It would be nice to have the same ease of use with custom levels,
  210                so that after declaring the custom VERBOSE/DIAG levels, we could
  211                use code like this:
  212             </p>
  213             <pre class="prettyprint">
  214 // nice to have: descriptive methods and no need to pass the level as a parameter
  215 logger.verbose("a verbose message");
  216 logger.diag("another message");
  217 logger.diag("java 8 lambda expression: {}", () -> someMethod());</pre>
  218             <p>The standard Logger interface cannot provide convenience methods for
  219               custom levels, but the next few sections introduce a code generation tool
  220               to create loggers that aim to make custom levels as easy to use
  221               as built-in levels.</p>
  222           </subsection>
  223           <a name="AddingOrReplacingLevels" />
  224           <subsection name="Adding or Replacing Log Levels">
  225             <p>
  226               We assume that most users want to <em>add</em> custom level methods to the Logger interface,
  227                in addition to the existing trace(), debug(), info(), ... methods for the built-in log levels.
  228             </p>
  229             <p>There is another use case, Domain Specific Language loggers, where we want to <em>replace</em>
  230                the existing trace(), debug(), info(), ... methods with all-custom methods.
  231             </p>
  232             <p>
  233               For example, for medical devices we could have only <tt>critical()</tt>, <tt>warning()</tt>,
  234               and <tt>advisory()</tt> methods.
  235               Another example could be a game that has only <tt>defcon1()</tt>, <tt>defcon2()</tt>,
  236               and <tt>defcon3()</tt> levels.
  237             </p>
  238             <p>
  239               If it were possible to hide existing log levels, users could customize the
  240               Logger interface to match their requirements. Some people may not want to
  241               have a FATAL or a TRACE level, for example. They would like to be able to
  242               create a custom Logger that only has debug(), info(), warn() and error() methods.
  243             </p>
  244           </subsection>
  245           <a name="CustomLoggers" />
  246           <subsection name="Generating Source Code for a Custom Logger Wrapper">
  247             <p>
  248               Common Log4J usage is to get an instance of the <tt>Logger</tt> interface from the
  249               <tt>LogManager</tt> and call the methods on this interface.
  250               However, the custom log Levels are not known in advance, so Log4J cannot provide
  251               an interface with convenience methods for these custom log Levels.
  252             </p>
  253             <p>
  254               To solve this, Log4J ships with a tool that generates source code for a
  255               Logger wrapper. The generated wrapper class has convenience methods for each
  256               custom log level, making custom levels just as easy to use as the built-in levels.
  257             </p>
  258             <p>
  259               There are two flavors of wrappers: ones that <em><b>extend</b></em> the Logger
  260               API (adding methods to the built-in levels) and ones that <em><b>customize</b></em>
  261               the Logger API (replacing the built-in methods).
  262             </p>
  263             <p>When generating the source code for a wrapper class, you need to specify:</p>
  264             <ul>
  265               <li>the fully qualified name of the class to generate
  266               </li>
  267               <li>the list of custom levels to support and their <tt>intLevel</tt> relative strength
  268               </li>
  269               <li>whether to extend <tt>Logger</tt> (and keep the existing built-in methods)
  270                 or have only methods for the custom log levels
  271               </li>
  272             </ul>
  273             <p>You would then include the generated source code in the project
  274               where you want to use custom log levels.</p>
  275           </subsection>
  276           <a name="ExampleUsage" />
  277           <subsection name="Example Usage of a Generated Logger Wrapper">
  278             <p>
  279               Here is an example of how one would use a generated logger wrapper with
  280               custom levels DIAG, NOTICE and VERBOSE:
  281             </p>
  282             <pre class="prettyprint linenums">
  283 // ExtLogger is a generated logger wrapper
  284 import com.mycompany.myproject.ExtLogger;
  285 
  286 public class MyService {
  287     // instead of Logger logger = LogManager.getLogger(MyService.class):
  288     private static final ExtLogger logger = ExtLogger.create(MyService.class);
  289 
  290     public void demoExtendedLogger() {
  291         // ...
  292         logger.trace("the built-in TRACE level");
  293         logger.verbose("a custom level: a VERBOSE message");
  294         logger.debug("the built-in DEBUG level");
  295         logger.notice("a custom level: a NOTICE message");
  296         logger.info("the built-in INFO level");
  297         logger.diag("a custom level: a DIAG message");
  298         logger.warn("the built-in WARN level");
  299         logger.error("the built-in ERROR level");
  300         logger.fatal("the built-in FATAL level");
  301         logger.notice("java 8 lambda expression only executed if NOTICE is enabled: {}", () -> someMethod());
  302         // ...
  303     }
  304     ...
  305 }</pre>
  306           </subsection>
  307           <a name="CodeGen" />
  308           <subsection name="Generating Extended Loggers">
  309             <p>
  310               Use the following command to generate a logger wrapper that adds methods to the built-in ones:
  311             </p>
  312             <pre class="prettyprint">
  313 java -cp log4j-core-${Log4jReleaseVersion}.jar org.apache.logging.log4j.core.tools.ExtendedLoggerGenerator \
  314         com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550 > com/mycomp/ExtLogger.java</pre>
  315             <p>
  316               This will generate source code for a logger wrapper that has the convenience methods
  317               for the built-in levels <em>as well as</em> the specified custom levels. The tool prints the
  318               generated source code to the console.
  319               By appending " &gt; <em>filename</em>" the output can be redirected to a file.
  320             </p><p>
  321               NOTE: Prior to log4j-2.9, this tool was an inner class <tt>Generate${dollar}ExtendedLogger</tt>.<br/>
  322                Under the bash shell on Unix/Mac/Linux the dollar character ${dollar} needs to be escaped, so the class name should
  323                be between single quotes 'org.apache.logging.log4j.core.tools.Generate${dollar}ExtendedLogger’.
  324             </p>
  325           </subsection>
  326           <subsection name="Generating Custom Loggers">
  327             <p>
  328               Use the following command to generate a logger wrapper that hides the built-in levels and has only custom levels:
  329             </p>
  330             <pre class="prettyprint">
  331 java -cp log4j-core-${Log4jReleaseVersion}.jar org.apache.logging.log4j.core.tools.CustomLoggerGenerator \
  332         com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 > com/mycomp/MyLogger.java</pre>
  333             <p>
  334               This will generate source code for a logger wrapper that <em>only</em> has convenience
  335               methods for the specified custom levels, <em>not</em> for the built-in levels.
  336               The tool prints the generated source code to the console.
  337               By appending " &gt; <em>filename</em>" the output can be redirected to a file.
  338             </p><p>
  339               NOTE: Prior to log4j-2.9, this tool was an inner class <tt>Generate${dollar}ExtendedLogger</tt>.<br/>
  340                Under the bash shell on Unix/Mac/Linux the dollar character ${dollar} needs to be escaped, so the class name should
  341                be between single quotes 'org.apache.logging.log4j.core.tools.Generate${dollar}CustomLogger’.
  342             </p>
  343           </subsection>
  344       </section>
  345 
  346     </body>
  347 </document>