LOG4J2-1802: Convert custom log levels manual page to asciidoc
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/fe2601c1 Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/fe2601c1 Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/fe2601c1 Branch: refs/heads/master Commit: fe2601c101070b69503ac94ba63758995384a1b2 Parents: a15df80 Author: Matt Sicker <boa...@gmail.com> Authored: Sun Apr 8 18:23:54 2018 -0500 Committer: Matt Sicker <boa...@gmail.com> Committed: Sun Apr 8 20:08:49 2018 -0500 ---------------------------------------------------------------------- src/site/asciidoc/manual/customloglevels.adoc | 323 +++++++++++++++++++ src/site/xdoc/manual/customloglevels.xml.vm | 347 --------------------- 2 files changed, 323 insertions(+), 347 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fe2601c1/src/site/asciidoc/manual/customloglevels.adoc ---------------------------------------------------------------------- diff --git a/src/site/asciidoc/manual/customloglevels.adoc b/src/site/asciidoc/manual/customloglevels.adoc new file mode 100644 index 0000000..e633b52 --- /dev/null +++ b/src/site/asciidoc/manual/customloglevels.adoc @@ -0,0 +1,323 @@ +//// + 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 + + https://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. +//// += Custom Log Levels +Remko Popma <rpo...@apache.org> + +[[top]] + +[#DefiningLevelsInCode] +== Defining Custom Log Levels in Code + +Log4j 2 supports custom log levels. Custom log levels can be defined in +code or in configuration. To define a custom log level in code, use the +`Level.forName()` method. This method creates a new level for the +specified name. After a log level is defined you can log messages at +this level by calling the `Logger.log()` method and passing the custom log +level: + +[source,java] +---- +// This creates the "VERBOSE" level if it does not exist yet. +final Level VERBOSE = Level.forName("VERBOSE", 550); + +final Logger logger = LogManager.getLogger(); +logger.log(VERBOSE, "a verbose message"); // use the custom VERBOSE level + +// Create and use a new custom level "DIAG". +logger.log(Level.forName("DIAG", 350), "a diagnostic message"); + +// Use (don't create) the "DIAG" custom level. +// Only do this *after* the custom level is created! +logger.log(Level.getLevel("DIAG"), "another diagnostic message"); + +// Using an undefined level results in an error: Level.getLevel() returns null, +// and logger.log(null, "message") throws an exception. +logger.log(Level.getLevel("FORGOT_TO_DEFINE"), "some message"); // throws exception! +---- + +When defining a custom log level, the `intLevel` parameter (550 and 350 +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 `intLevel` of the built-in log levels. + +.Standard log levels built-in to Log4j +[cols=",>",options="header"] +|======================== +|Standard Level |intLevel +|OFF |0 +|FATAL |100 +|ERROR |200 +|WARN |300 +|INFO |400 +|DEBUG |500 +|TRACE |600 +|ALL |`Integer.MAX_VALUE` +|======================== + +[#DefiningLevelsInConfiguration] +== Defining Custom Log Levels in Configuration + +Custom log levels can also be defined in configuration. This is +convenient for using a custom level in a logger filter or an appender +filter. Similar to defining log levels in code, a custom level must be +defined first, before it can be used. If a logger or appender is +configured with an undefined level, that logger or appender will be +invalid and will not process any log events. + +The *CustomLevel* configuration element creates a custom level. +Internally it calls the same `Level.forName()` method discussed above. + +.CustomLevel Parameters +[cols="m,,4",options="header"] +|=== +|Parameter Name |Type |Description + +|name +|String +|The name of the custom level. Note that level names are +case sensitive. The convention is to use all upper-case names. + +|intLevel +|integer +|Determines where the custom level exists in relation +to the standard levels built-in to Log4j 2 (see the table above). +|=== + +The following example shows a configuration that defines some custom log +levels and uses a custom log level to filter log events sent to the +console. + +[source,xml] +---- +<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="WARN"> + <!-- Define custom levels before using them for filtering below. --> + <CustomLevels> + <CustomLevel name="DIAG" intLevel="350" /> + <CustomLevel name="NOTICE" intLevel="450" /> + <CustomLevel name="VERBOSE" intLevel="550" /> + </CustomLevels> + + <Appenders> + <Console name="Console" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/> + </Console> + <File name="MyFile" fileName="logs/app.log"> + <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/> + </File> + </Appenders> + <Loggers> + <Root level="trace"> + <!-- Only events at DIAG level or more specific are sent to the console. --> + <AppenderRef ref="Console" level="diag" /> + <AppenderRef ref="MyFile" level="trace" /> + </Root> + </Loggers> +</Configuration> +---- + +[#StandardLoggerInterface] +== Convenience Methods for the Built-in Log Levels + +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 24 `debug()` methods that support the DEBUG level: + +[source,java] +---- +// 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) +// lambda support methods added in 2.4 +debug(Marker, MessageSupplier) +debug(Marker, MessageSupplier, Throwable) +debug(Marker, String, Supplier<?>...) +debug(Marker, Supplier<?>) +debug(Marker, Supplier<?>, Throwable) +debug(MessageSupplier) +debug(MessageSupplier, Throwable) +debug(String, Supplier<?>...) +debug(Supplier<?>) +debug(Supplier<?>, Throwable) +---- + +Similar methods exist for the other built-in levels. Custom levels, in +contrast, need to pass in the log level as an extra parameter. + +[source,java] +---- +// need to pass the custom level as a parameter +logger.log(VERBOSE, "a verbose message"); +logger.log(Level.forName("DIAG", 350), "another message"); +---- + +It would be nice to have the same ease of use with custom levels, so +that after declaring the custom VERBOSE/DIAG levels, we could use code +like this: + +[source,java] +---- +// nice to have: descriptive methods and no need to pass the level as a parameter +logger.verbose("a verbose message"); +logger.diag("another message"); +logger.diag("java 8 lambda expression: {}", () -> someMethod()); +---- + +The standard Logger interface cannot provide convenience methods for +custom levels, but the next few sections introduce a code generation +tool to create loggers that aim to make custom levels as easy to use as +built-in levels. + +[#AddingOrReplacingLevels] +== Adding or Replacing Log Levels + +We assume that most users want to _add_ custom level methods to the +Logger interface, in addition to the existing `trace()`, `debug()`, `info()`, +... methods for the built-in log levels. + +There is another use case, Domain Specific Language loggers, where we +want to _replace_ the existing `trace()`, `debug()`, `info()`, ... methods +with all-custom methods. + +For example, for medical devices we could have only `critical()`, +`warning()`, and `advisory()` methods. Another example could be a game +that has only `defcon1()`, `defcon2()`, and `defcon3()` levels. + +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. + +[#CustomLoggers] +== Generating Source Code for a Custom Logger Wrapper + +Common Log4j usage is to get an instance of the `Logger` interface from +the `LogManager` 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. + +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. + +There are two flavors of wrappers: ones that _*extend*_ the Logger API +(adding methods to the built-in levels) and ones that _*customize*_ the +Logger API (replacing the built-in methods). + +When generating the source code for a wrapper class, you need to +specify: + +* the fully qualified name of the class to generate +* the list of custom levels to support and their `intLevel` relative +strength +* whether to extend `Logger` (and keep the existing built-in methods) or +have only methods for the custom log levels + +You would then include the generated source code in the project where +you want to use custom log levels. + +[#ExampleUsage] +== Example Usage of a Generated Logger Wrapper + +Here is an example of how one would use a generated logger wrapper with +custom levels DIAG, NOTICE and VERBOSE: + +[source,java] +---- +// 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 demoExtendedLogger() { + // ... + 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"); + logger.notice("java 8 lambda expression only executed if NOTICE is enabled: {}", () -> someMethod()); + // ... + } + ... +} +---- + +[#CodeGen] +== Generating Extended Loggers + +Use the following command to generate a logger wrapper that adds methods +to the built-in ones: + +[source,sh,subs="attributes"] +---- +java -cp log4j-core-{Log4jReleaseVersion}.jar org.apache.logging.log4j.core.tools.ExtendedLoggerGenerator \ + com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550 > com/mycomp/ExtLogger.java +---- + +This will generate source code for a logger wrapper that has the +convenience methods for the built-in levels _as well as_ the specified +custom levels. The tool prints the generated source code to the console. +By appending " > _filename_" the output can be redirected to a file. + +NOTE: Prior to log4j-2.9, this tool was an inner class +`Generate$ExtendedLogger`. + +Under the bash shell on Unix/Mac/Linux the dollar character $ needs to +be escaped, so the class name should be between single quotes +'org.apache.logging.log4j.core.tools.Generate$ExtendedLoggerâ. + +== Generating Custom Loggers + +Use the following command to generate a logger wrapper that hides the +built-in levels and has only custom levels: + +[source,sh,subs="attributes"] +---- +java -cp log4j-core-{Log4jReleaseVersion}.jar org.apache.logging.log4j.core.tools.CustomLoggerGenerator \ + com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 > com/mycomp/MyLogger.java +---- + +This will generate source code for a logger wrapper that _only_ has +convenience methods for the specified custom levels, _not_ for the +built-in levels. The tool prints the generated source code to the +console. By appending " > _filename_" the output can be redirected to a +file. + +NOTE: Prior to log4j-2.9, this tool was an inner class `Generate$ExtendedLogger`. +Under the bash shell on Unix/Mac/Linux the dollar character $ needs to +be escaped, so the class name should be between single quotes +'org.apache.logging.log4j.core.tools.Generate$CustomLoggerâ. http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fe2601c1/src/site/xdoc/manual/customloglevels.xml.vm ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/customloglevels.xml.vm b/src/site/xdoc/manual/customloglevels.xml.vm deleted file mode 100644 index 7a74a1c..0000000 --- a/src/site/xdoc/manual/customloglevels.xml.vm +++ /dev/null @@ -1,347 +0,0 @@ -<?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. ---> -#set($dollar = '$') - -<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="rpo...@apache.org">Remko Popma</author> - </properties> - - <body> - <a name="top" /> - <section name="Custom Log Levels"> - <a name="DefiningLevelsInCode" /> - <subsection name="Defining Custom Log Levels in Code"> - <p> - Log4J 2 supports custom log levels. Custom log levels can be defined in code - or in configuration. To define a custom log level in code, use the - <tt>Level.forName()</tt> method. This method creates a new - level for the specified name. After a log level is defined you can log - messages at this level by calling the Logger.log() method and passing - the custom log level: - </p> - <pre class="prettyprint"> -// This creates the "VERBOSE" level if it does not exist yet. -final Level VERBOSE = Level.forName("VERBOSE", 550); - -final Logger logger = LogManager.getLogger(); -logger.log(VERBOSE, "a verbose message"); // use the custom VERBOSE level - -// Create and use a new custom level "DIAG". -logger.log(Level.forName("DIAG", 350), "a diagnostic message"); - -// Use (don't create) the "DIAG" custom level. -// Only do this *after* the custom level is created! -logger.log(Level.getLevel("DIAG"), "another diagnostic message"); - -// Using an undefined level results in an error: Level.getLevel() returns null, -// and logger.log(null, "message") throws an exception. -logger.log(Level.getLevel("FORGOT_TO_DEFINE"), "some message"); // throws exception!</pre> - <p>When defining a custom log level, the <tt>intLevel</tt> parameter (550 and 350 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> - </subsection> - <a name="DefiningLevelsInConfiguration" /> - <subsection name="Defining Custom Log Levels in Configuration"> - <p> - Custom log levels can also be defined in configuration. - This is convenient for using a custom level in a logger filter - or an appender filter. Similar to defining log levels in code, - a custom level must be defined first, before it can be used. - If a logger or appender is configured with an undefined level, - that logger or appender will be invalid and will not process any log events. - </p> - <p> - The <b>CustomLevel</b> configuration element creates a custom level. - Internally it calls the same <tt>Level.forName()</tt> method discussed above. - </p> - <table> - <caption align="top">CustomLevel Parameters</caption> - <tr> - <th>Parameter Name</th> - <th>Type</th> - <th>Description</th> - </tr> - <tr> - <td>name</td> - <td>String</td> - <td>The name of the custom level. Note that level names are case sensitive. - The convention is to use all upper-case names.</td> - </tr> - <tr> - <td>intLevel</td> - <td>integer</td> - <td>Determines where the custom level exists in relation to the - standard levels built-in to Log4J 2 (see the table above).</td> - </tr> - </table> - <p> - The following example shows a configuration that defines some custom - log levels and uses a custom log level to filter log events sent to the console. - </p> - <pre class="prettyprint linenums"><![CDATA[ -<?xml version="1.0" encoding="UTF-8"?> -<Configuration status="WARN"> - <!-- Define custom levels before using them for filtering below. --> - <CustomLevels> - <CustomLevel name="DIAG" intLevel="350" /> - <CustomLevel name="NOTICE" intLevel="450" /> - <CustomLevel name="VERBOSE" intLevel="550" /> - </CustomLevels> - - <Appenders> - <Console name="Console" target="SYSTEM_OUT"> - <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/> - </Console> - <File name="MyFile" fileName="logs/app.log"> - <PatternLayout pattern="%d %-7level %logger{36} - %msg%n"/> - </File> - </Appenders> - <Loggers> - <Root level="trace"> - <!-- Only events at DIAG level or more specific are sent to the console. --> - <AppenderRef ref="Console" level="diag" /> - <AppenderRef ref="MyFile" level="trace" /> - </Root> - </Loggers> -</Configuration>]]></pre> - </subsection> - <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 24 <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) -// lambda support methods added in 2.4 -debug(Marker, MessageSupplier) -debug(Marker, MessageSupplier, Throwable) -debug(Marker, String, Supplier<?>...) -debug(Marker, Supplier<?>) -debug(Marker, Supplier<?>, Throwable) -debug(MessageSupplier) -debug(MessageSupplier, Throwable) -debug(String, Supplier<?>...) -debug(Supplier<?>) -debug(Supplier<?>, Throwable)</pre> - <p> - Similar methods exist for the other built-in levels. - Custom levels, in contrast, need to pass in the log level as an extra parameter. - </p> - <pre class="prettyprint"> -// need to pass the custom level as a parameter -logger.log(VERBOSE, "a verbose message"); -logger.log(Level.forName("DIAG", 350), "another message");</pre> - <p>It would be nice to have the same ease of use with custom levels, - so that after declaring the custom VERBOSE/DIAG levels, we could - use code like this: - </p> - <pre class="prettyprint"> -// nice to have: descriptive methods and no need to pass the level as a parameter -logger.verbose("a verbose message"); -logger.diag("another message"); -logger.diag("java 8 lambda expression: {}", () -> someMethod());</pre> - <p>The standard Logger interface cannot provide convenience methods for - custom levels, but the next few sections introduce a code generation tool - to create loggers that aim to make custom levels as easy to use - as built-in levels.</p> - </subsection> - <a name="AddingOrReplacingLevels" /> - <subsection name="Adding or Replacing Log Levels"> - <p> - We assume that most users want to <em>add</em> custom level methods 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 demoExtendedLogger() { - // ... - 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"); - logger.notice("java 8 lambda expression only executed if NOTICE is enabled: {}", () -> someMethod()); - // ... - } - ... -}</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 -cp log4j-core-${Log4jReleaseVersion}.jar org.apache.logging.log4j.core.tools.ExtendedLoggerGenerator \ - com.mycomp.ExtLogger DIAG=350 NOTICE=450 VERBOSE=550 > com/mycomp/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. - By appending " > <em>filename</em>" the output can be redirected to a file. - </p><p> - NOTE: Prior to log4j-2.9, this tool was an inner class <tt>Generate${dollar}ExtendedLogger</tt>.<br/> - Under the bash shell on Unix/Mac/Linux the dollar character ${dollar} needs to be escaped, so the class name should - be between single quotes 'org.apache.logging.log4j.core.tools.Generate${dollar}ExtendedLoggerâ. - </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 -cp log4j-core-${Log4jReleaseVersion}.jar org.apache.logging.log4j.core.tools.CustomLoggerGenerator \ - com.mycomp.MyLogger DEFCON1=350 DEFCON2=450 DEFCON3=550 > com/mycomp/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. - By appending " > <em>filename</em>" the output can be redirected to a file. - </p><p> - NOTE: Prior to log4j-2.9, this tool was an inner class <tt>Generate${dollar}ExtendedLogger</tt>.<br/> - Under the bash shell on Unix/Mac/Linux the dollar character ${dollar} needs to be escaped, so the class name should - be between single quotes 'org.apache.logging.log4j.core.tools.Generate${dollar}CustomLoggerâ. - </p> - </subsection> - </section> - - </body> -</document>