Repository: logging-log4j2 Updated Branches: refs/heads/master 49442e47f -> a39a8559e
LOG4J2-1802: Convert architecture 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/967ebdad Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/967ebdad Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/967ebdad Branch: refs/heads/master Commit: 967ebdad81c522ccde808acf2c6889c18003eed0 Parents: bc28fda Author: Matt Sicker <boa...@gmail.com> Authored: Sat Apr 7 13:49:26 2018 -0500 Committer: Matt Sicker <boa...@gmail.com> Committed: Sat Apr 7 13:49:26 2018 -0500 ---------------------------------------------------------------------- src/site/asciidoc/manual/architecture.adoc | 474 +++++++++++++++ src/site/xdoc/manual/architecture.xml | 737 ------------------------ 2 files changed, 474 insertions(+), 737 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/967ebdad/src/site/asciidoc/manual/architecture.adoc ---------------------------------------------------------------------- diff --git a/src/site/asciidoc/manual/architecture.adoc b/src/site/asciidoc/manual/architecture.adoc new file mode 100644 index 0000000..73fa6e1 --- /dev/null +++ b/src/site/asciidoc/manual/architecture.adoc @@ -0,0 +1,474 @@ +//// + 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. +//// += Architecture +Ralph Goers <rgo...@apache.org> + +== Main Components + +Log4j uses the classes shown in the diagram below. + +image:../images/Log4jClasses.jpg[Log4j 2 Class Relationships,title="Log4j 2 Class Relationships"] + +Applications using the Log4j 2 API will request a Logger with a specific +name from the LogManager. The LogManager will locate the appropriate +LoggerContext and then obtain the Logger from it. If the Logger must be +created it will be associated with the LoggerConfig that contains either +a) the same name as the Logger, b) the name of a parent package, or c) +the root LoggerConfig. LoggerConfig objects are created from Logger +declarations in the configuration. The LoggerConfig is associated with +the Appenders that actually deliver the LogEvents. + +=== Logger Hierarchy + +The first and foremost advantage of any logging API over plain +`System.out.println` resides in its ability to disable certain log +statements while allowing others to print unhindered. This capability +assumes that the logging space, that is, the space of all possible +logging statements, is categorized according to some developer-chosen +criteria. + +In Log4j 1.x the Logger Hierarchy was maintained through a relationship +between Loggers. In Log4j 2 this relationship no longer exists. Instead, +the hierarchy is maintained in the relationship between LoggerConfig +objects. + +Loggers and LoggerConfigs are named entities. Logger names are +case-sensitive and they follow the hierarchical naming rule: + +Named Hierarchy:: +A LoggerConfig is said to be an _ancestor_ of another LoggerConfig if +its name followed by a dot is a prefix of the _descendant_ logger +name. A LoggerConfig is said to be a _parent_ of a _child_ +LoggerConfig if there are no ancestors between itself and the +descendant LoggerConfig. + +For example, the LoggerConfig named `"com.foo"` is a parent of the +LoggerConfig named`"com.foo.Bar"`. Similarly, `"java"` is a parent of +`"java.util"` and an ancestor of `"java.util.Vector"`. This naming +scheme should be familiar to most developers. + +The root LoggerConfig resides at the top of the LoggerConfig hierarchy. +It is exceptional in that it always exists and it is part of every +hierarchy. A Logger that is directly linked to the root LoggerConfig can +be obtained as follows: + +[source,java] +---- +Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME); +---- + +Alternatively, and more simply: + +[source,java] +---- +Logger logger = LogManager.getRootLogger(); +---- + +All other Loggers can be retrieved using the +link:../log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)[`LogManager.getLogger`] +static method by passing the name of the desired Logger. Further +information on the Logging API can be found in the +link:../log4j-api/api.html[Log4j 2 API]. + +=== LoggerContext + +The +link:../log4j-core/apidocs/org/apache/logging/log4j/core/LoggerContext.html[`LoggerContext`] +acts as the anchor point for the Logging system. However, it is possible +to have multiple active LoggerContexts in an application depending on +the circumstances. More details on the LoggerContext are in the +link:logsep.html[Log Separation] section. + +=== Configuration + +Every LoggerContext has an active +link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]. +The Configuration contains all the Appenders, context-wide Filters, +LoggerConfigs and contains the reference to the StrSubstitutor. During +reconfiguration two Configuration objects will exist. Once all Loggers +have been redirected to the new Configuration, the old Configuration +will be stopped and discarded. + +=== Logger + +As stated previously, Loggers are created by calling +link:../log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)[`LogManager.getLogger`]. +The Logger itself performs no direct actions. It simply has a name and +is associated with a LoggerConfig. It extends +link:../log4j-api/apidocs/org/apache/logging/log4j/spi/AbstractLogger.html[`AbstractLogger`] +and implements the required methods. As the configuration is modified +Loggers may become associated with a different LoggerConfig, thus +causing their behavior to be modified. + +Retrieving Loggers + +Calling the `LogManager.getLogger` method with the same name will always +return a reference to the exact same Logger object. + +For example, in + +[source,java] +---- +Logger x = LogManager.getLogger("wombat"); +Logger y = LogManager.getLogger("wombat"); +---- + +`x` and `y` refer to _exactly_ the same Logger object. + +Configuration of the log4j environment is typically done at application +initialization. The preferred way is by reading a configuration file. +This is discussed in link:configuration.html[Configuration]. + +Log4j makes it easy to name Loggers by _software component_. This can be +accomplished by instantiating a Logger in each class, with the logger +name equal to the fully qualified name of the class. This is a useful +and straightforward method of defining loggers. As the log output bears +the name of the generating Logger, this naming strategy makes it easy to +identify the origin of a log message. However, this is only one +possible, albeit common, strategy for naming loggers. Log4j does not +restrict the possible set of loggers. The developer is free to name the +loggers as desired. + +Since naming Loggers after their owning class is such a common idiom, +the convenience method `LogManager.getLogger()` is provided to +automatically use the calling class's fully qualified class name as the +Logger name. + +Nevertheless, naming loggers after the class where they are located +seems to be the best strategy known so far. + +=== LoggerConfig + +link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/LoggerConfig.html[`LoggerConfig`] +objects are created when Loggers are declared in the logging +configuration. The LoggerConfig contains a set of Filters that must +allow the LogEvent to pass before it will be passed to any Appenders. It +contains references to the set of Appenders that should be used to +process the event. + +==== Log Levels + +LoggerConfigs will be assigned a Log +link:../log4j-api/apidocs/org/apache/logging/log4j/Level.html[`Level`]. +The set of built-in levels includes TRACE, DEBUG, INFO, WARN, ERROR, and +FATAL. Log4j 2 also supports link:customloglevels.html[custom log +levels]. Another mechanism for getting more granularity is to use +link:../log4j-api/api.html#Markers[Markers] instead. + +http://logging.apache.org/log4j/1.2/manual.html[Log4j 1.x] and +http://logback.qos.ch/manual/architecture.html#effectiveLevel[Logback] +both have the concept of "Level Inheritance". In Log4j 2, Loggers and +LoggerConfigs are two different objects so this concept is implemented +differently. Each Logger references the appropriate LoggerConfig which +in turn can reference its parent, thus achieving the same effect. + +Below are five tables with various assigned level values and the +resulting levels that will be associated with each Logger. Note that in +all these cases if the root LoggerConfig is not configured a default +Level will be assigned to it. + +.Example 1 +[cols=",,,",options="header",] +|==================================================================== +|Logger Name |Assigned LoggerConfig |LoggerConfig Level |Logger Level +|root |root |DEBUG |DEBUG +|X |root |DEBUG |DEBUG +|X.Y |root |DEBUG |DEBUG +|X.Y.Z |root |DEBUG |DEBUG +|==================================================================== + +In example 1 above, only the root logger is configured and has a Log +Level. All the other Loggers reference the root LoggerConfig and use its +Level. + +.Example 2 +[cols=",,,",options="header",] +|============================================================= +|Logger Name |Assigned LoggerConfig |LoggerConfig Level |Level +|root |root |DEBUG |DEBUG +|X |X |ERROR |ERROR +|X.Y |X.Y |INFO |INFO +|X.Y.Z |X.Y.Z |WARN |WARN +|============================================================= + +In example 2, all loggers have a configured LoggerConfig and obtain +their Level from it. + +.Example 3 +[cols=",,,",options="header",] +|============================================================= +|Logger Name |Assigned LoggerConfig |LoggerConfig Level |Level +|root |root |DEBUG |DEBUG +|X |X |ERROR |ERROR +|X.Y |X |ERROR |ERROR +|X.Y.Z |X.Y.Z |WARN |WARN +|============================================================= + +In example 3, the loggers`root`, `X` and `X.Y.Z` each have a configured +LoggerConfig with the same name. The Logger `X.Y` does not have a +configured LoggerConfig with a matching name so uses the configuration +of LoggerConfig `X` since that is the LoggerConfig whose name has the +longest match to the start of the Logger's name. + +.Example 4 +[cols=",,,",options="header",] +|============================================================= +|Logger Name |Assigned LoggerConfig |LoggerConfig Level |level +|root |root |DEBUG |DEBUG +|X |X |ERROR |ERROR +|X.Y |X |ERROR |ERROR +|X.Y.Z |X |ERROR |ERROR +|============================================================= + +In example 4, the loggers `root` and `X` each have a Configured +LoggerConfig with the same name. The loggers `X.Y` and `X.Y.Z` do not +have configured LoggerConfigs and so get their Level from the +LoggerConfig assigned to them,`X`, since it is the LoggerConfig whose +name has the longest match to the start of the Logger's name. + +.Example 5 +[cols=",,,",options="header",] +|============================================================= +|Logger Name |Assigned LoggerConfig |LoggerConfig Level |level +|root |root |DEBUG |DEBUG +|X |X |ERROR |ERROR +|X.Y |X.Y |INFO |INFO +|X.YZ |X |ERROR |ERROR +|============================================================= + +In example 5, the loggers`root`.`X`, and `X.Y` each have a Configured +LoggerConfig with the same name. The logger `X.YZ` does not have +configured LoggerConfig and so gets its Level from the LoggerConfig +assigned to it,`X`, since it is the LoggerConfig whose name has the +longest match to the start of the Logger's name. It is not associated +with LoggerConfig `X.Y` since tokens after periods must match exactly. + +.Example 6 +[cols=4*,options="header"] +|=== +|Logger Name |Assigned LoggerConfig |LoggerConfig Level |Level +|root |root |DEBUG |DEBUG +|X |X |ERROR |ERROR +|X.Y |X.Y | |ERROR +|X.Y.Z |X.Y | |ERROR +|=== + +In example 6, LoggerConfig X.Y it has no configured level so it inherits +its level from LoggerConfig X. Logger X.Y.Z uses LoggerConfig X.Y since +it doesn't have a LoggerConfig with a name that exactly matches. It too +inherits its logging level from LoggerConfig X. + +The table below illustrates how Level filtering works. In the table, the +vertical header shows the Level of the LogEvent, while the horizontal +header shows the Level associated with the appropriate LoggerConfig. The +intersection identifies whether the LogEvent would be allowed to pass +for further processing (Yes) or discarded (No). + +[cols=8*,options="header"] +|=== +|Event Level +7+|LoggerConfig Level + +|Â |`TRACE` |`DEBUG` |`INFO` |`WARN` |`ERROR` |`FATAL` |`OFF` + +|`ALL` |â |â |â |â |â |â |â + +|`TRACE` |â |â |â |â |â |â |â + +|`DEBUG` |â |â |â |â |â |â |â + +|`INFO` |â |â |â |â |â |â |â + +|`WARN` |â |â |â |â |â |â |â + +|`ERROR` |â |â |â |â |â |â |â + +|`FATAL` |â |â |â |â |â |â |â + +|`OFF` |â |â |â |â |â |â |â +|=== + +=== Filter + +In addition to the automatic log Level filtering that takes place as +described in the previous section, Log4j provides +link:../log4j-core/apidocs/org/apache/logging/log4j/core/Filter.html[`Filter`]s +that can be applied before control is passed to any LoggerConfig, after +control is passed to a LoggerConfig but before calling any Appenders, +after control is passed to a LoggerConfig but before calling a specific +Appender, and on each Appender. In a manner very similar to firewall +filters, each Filter can return one of three results, `Accept`, `Deny` +or `Neutral`. A response of `Accept` means that no other Filters should +be called and the event should progress. A response of `Deny` means the +event should be immediately ignored and control should be returned to +the caller. A response of `Neutral` indicates the event should be passed +to other Filters. If there are no other Filters the event will be +processed. + +Although an event may be accepted by a Filter the event still might not +be logged. This can happen when the event is accepted by the +pre-LoggerConfig Filter but is then denied by a LoggerConfig filter or +is denied by all Appenders. + +=== Appender + +The ability to selectively enable or disable logging requests based on +their logger is only part of the picture. Log4j allows logging requests +to print to multiple destinations. In log4j speak, an output destination +is called an +link:../log4j-core/apidocs/org/apache/logging/log4j/core/Appender.html[`Appender`]. +Currently, appenders exist for the console, files, remote socket +servers, Apache Flume, JMS, remote UNIX Syslog daemons, and various +database APIs. See the section on link:appenders.html[Appenders] for +more details on the various types available. More than one Appender can +be attached to a Logger. + +An Appender can be added to a Logger by calling the +link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/Configuration.html#addLoggerAppender(org.apache.logging.log4j.core.Logger,%20org.apache.logging.log4j.core.Appender)[`addLoggerAppender`] +method of the current Configuration. If a LoggerConfig matching the name +of the Logger does not exist, one will be created, the Appender will be +attached to it and then all Loggers will be notified to update their +LoggerConfig references. + +*Each enabled logging request for a given logger will be forwarded to +all the appenders in that Logger's LoggerConfig as well as the Appenders +of the LoggerConfig's parents.* In other words, Appenders are inherited +additively from the LoggerConfig hierarchy. For example, if a console +appender is added to the root logger, then all enabled logging requests +will at least print on the console. If in addition a file appender is +added to a LoggerConfig, say _C_, then enabled logging requests for _C_ +and _C_'s children will print in a file _and_ on the console. It is +possible to override this default behavior so that Appender accumulation +is no longer additive by setting `additivity="false"` on the Logger +declaration in the configuration file. + +The rules governing appender additivity are summarized below. + +Appender Additivity:: +The output of a log statement of Logger _L_ will go to all the +Appenders in the LoggerConfig associated with _L_ and the ancestors of +that LoggerConfig. This is the meaning of the term "appender +additivity". ++ +However, if an ancestor of the LoggerConfig associated with Logger +_L_, say _P_, has the additivity flag set to `false`, then _L_'s +output will be directed to all the appenders in _L_'s LoggerConfig and +it's ancestors up to and including _P_ but not the Appenders in any of +the ancestors of _P_. ++ +Loggers have their additivity flag set to `true` by default. + +The table below shows an example: + +|=== +|Logger Name |Added Appenders |Additivity Flag |Output Targets |Comment + +|root +|A1 +|not applicable +|A1 +|The root logger has no parent so additivity does not apply to it. + +|x +|A-x1, A-x2 +|true +|A1, A-x1, A-x2 +|Appenders of "x" and root. + +|x.y +|none +|true +|A1, A-x1, A-x2 +|Appenders of "x" and root. It would not be typical to configure a Logger with no Appenders. + +|x.y.z +|A-xyz1 +|true +|A1, A-x1, A-x2, A-xyz1 +|Appenders in "x.y.z", "x" and root. + +|security +|A-sec +|false +|A-sec +|No appender accumulation since the additivity flag is set to `false`. + +|security.access +|none +|true +|A-sec +|Only appenders of "security" because the additivity flag in "security" is set to `false`. +|=== + +=== Layout + +More often than not, users wish to customize not only the output +destination but also the output format. This is accomplished by +associating a +link:../log4j-core/apidocs/org/apache/logging/log4j/core/Layout.html[`Layout`] +with an Appender. The Layout is responsible for formatting the LogEvent +according to the user's wishes, whereas an appender takes care of +sending the formatted output to its destination. The +link:../log4j-core/apidocs/org/apache/logging/log4j/core/layout/PatternLayout.html[`PatternLayout`], +part of the standard log4j distribution, lets the user specify the +output format according to conversion patterns similar to the C language +`printf` function. + +For example, the PatternLayout with the conversion pattern "%r [%t] %-5p +%c - %m%n" will output something akin to: + +.... +176 [main] INFO org.foo.Bar - Located nearest gas station. +.... + +The first field is the number of milliseconds elapsed since the start of +the program. The second field is the thread making the log request. The +third field is the level of the log statement. The fourth field is the +name of the logger associated with the log request. The text after the +'-' is the message of the statement. + +Log4j comes with many different link:layouts.html[Layouts] for various +use cases such as JSON, XML, HTML, and Syslog (including the new RFC +5424 version). Other appenders such as the database connectors fill in +specified fields instead of a particular textual layout. + +Just as importantly, log4j will render the content of the log message +according to user specified criteria. For example, if you frequently +need to log `Oranges`, an object type used in your current project, then +you can create an OrangeMessage that accepts an Orange instance and pass +that to Log4j so that the Orange object can be formatted into an +appropriate byte array when required. + +=== StrSubstitutor and StrLookup + +The +link:../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrSubstitutor.html[`StrSubstitutor`] +class and +link:../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrLookup.html[`StrLookup`] +interface were borrowed from +https://commons.apache.org/proper/commons-lang/[Apache Commons Lang] and +then modified to support evaluating LogEvents. In addition the +link:../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/Interpolator.html[`Interpolator`] +class was borrowed from Apache Commons Configuration to allow the +StrSubstitutor to evaluate variables that from multiple StrLookups. It +too was modified to support evaluating LogEvents. Together these provide +a mechanism to allow the configuration to reference variables coming +from System Properties, the configuration file, the ThreadContext Map, +StructuredData in the LogEvent. The variables can either be resolved +when the configuration is processed or as each event is processed, if +the component is capable of handling it. See link:lookups.html[Lookups] +for more information. http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/967ebdad/src/site/xdoc/manual/architecture.xml ---------------------------------------------------------------------- diff --git a/src/site/xdoc/manual/architecture.xml b/src/site/xdoc/manual/architecture.xml deleted file mode 100644 index 524e031..0000000 --- a/src/site/xdoc/manual/architecture.xml +++ /dev/null @@ -1,737 +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. ---> - -<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>Log4j 2 Architecture</title> - <author email="rgo...@apache.org">Ralph Goers</author> - </properties> - - <body> - <section name="Architecture"> - <subsection name="Main Components"> - <p>Log4j uses the classes shown in the diagram below.</p> - <img src="../images/Log4jClasses.jpg" title="Log4j 2 Class Relationships" - alt="Log4j 2 Class Relationships"/> - <p>Applications using the Log4j 2 API will request a Logger with a specific name from the - LogManager. The LogManager will locate the appropriate LoggerContext and then obtain the Logger from it. - If the Logger must be created it will be associated with the LoggerConfig that contains either a) the - same name as the Logger, b) the name of a parent package, or c) the root LoggerConfig. LoggerConfig - objects are created from Logger declarations in the configuration. The LoggerConfig is associated with - the Appenders that actually deliver the LogEvents. - </p> - <h4>Logger Hierarchy</h4> - <p>The first and foremost advantage of any logging API over plain - <code>System.out.println</code> - resides in its ability to disable - certain log statements while allowing others to print unhindered. This - capability assumes that the logging space, that is, the space of all - possible logging statements, is categorized according to some - developer-chosen criteria. - </p> - <p>In Log4j 1.x the Logger Hierarchy was maintained through a relationship between Loggers. - In Log4j 2 this relationship no longer exists. Instead, the hierarchy is maintained - in the relationship between LoggerConfig objects. - </p> - - <p>Loggers and LoggerConfigs are named entities. Logger names are case-sensitive and - they follow the hierarchical naming rule: - </p> - - <div class="well"> - <dl> - <dt>Named Hierarchy</dt> - <dd> - A LoggerConfig is said to be an <em>ancestor</em> of another LoggerConfig if its name followed by a dot - is a prefix of the <em>descendant</em> logger name. A LoggerConfig is said to be a <em>parent</em> of a - <em>child</em> LoggerConfig if there are no ancestors between itself and the descendant LoggerConfig. - </dd> - </dl> - </div> - - <p>For example, the LoggerConfig named - <code>"com.foo"</code> - is a parent - of the LoggerConfig named<code>"com.foo.Bar"</code>. Similarly, - <code>"java"</code> - is a parent of - <code>"java.util"</code> - and an - ancestor of <code>"java.util.Vector"</code>. This naming scheme - should be familiar to most developers. - </p> - - <p>The root LoggerConfig resides at the top of the LoggerConfig hierarchy. It - is exceptional in that it always exists and it is part of every hierarchy. A Logger - that is directly linked to the root LoggerConfig can be obtained as follows: - </p> - <pre class="prettyprint">Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);</pre> - <p> - Alternatively, and more simply: - </p> - <pre class="prettyprint">Logger logger = LogManager.getRootLogger();</pre> - <p> - All other Loggers can be retrieved using the - <a href="../log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)"> - LogManager.getLogger - </a> - static method by passing the name of the desired Logger. Further information on the Logging - API can be found in the <a href="../log4j-api/api.html">Log4j 2 API</a>. - </p> - <h4>LoggerContext</h4> - <p> - The - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/LoggerContext.html">LoggerContext</a> - acts as the anchor point for the Logging system. However, it is possible to have multiple active - LoggerContexts in an application depending on the circumstances. - More details on the LoggerContext are in the <a href="logsep.html">Log Separation</a> section. - </p> - <h4>Configuration</h4> - <p>Every LoggerContext has an active - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/config/Configuration.html"> - Configuration</a>. - The Configuration contains all the Appenders, - context-wide Filters, LoggerConfigs and contains the reference to the StrSubstitutor. During - reconfiguration two Configuration objects will exist. Once all Loggers have been redirected to - the new Configuration, the old Configuration will be stopped and discarded. - </p> - <h4>Logger</h4> - <p>As stated previously, Loggers are created by calling - <a href="../log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.String)">LogManager.getLogger</a>. - The Logger itself performs no direct actions. It simply has a name and is associated with a LoggerConfig. - It extends - <a href="../log4j-api/apidocs/org/apache/logging/log4j/spi/AbstractLogger.html"> - AbstractLogger - </a> - and implements the required methods. As the configuration is modified Loggers may become associated - with a different LoggerConfig, thus causing their behavior to be modified. - </p> - <h5>Retrieving Loggers</h5> - <p> - Calling the <code>LogManager.getLogger</code> method with the same name will always return a reference to the - exact same Logger object. - </p> - - <p>For example, in - </p> -<pre class="prettyprint"> -Logger x = LogManager.getLogger("wombat"); -Logger y = LogManager.getLogger("wombat"); -</pre> - <p> - <code>x</code> and <code>y</code> refer to <em>exactly</em> the same Logger object. - </p> - - <p>Configuration of the log4j environment is typically done at - application initialization. The preferred way is by reading a - configuration file. This is discussed in <a href="configuration.html">Configuration</a>. - </p> - - <p>Log4j makes it easy to name Loggers by <em>software component</em>. This can be accomplished - by instantiating a Logger in each class, with the logger name equal to the fully - qualified name of the class. This is a useful and straightforward - method of defining loggers. As the log output bears the name of the - generating Logger, this naming strategy makes it easy to identify - the origin of a log message. However, this is only one possible, - albeit common, strategy for naming loggers. Log4j does not restrict - the possible set of loggers. The developer is free to name the - loggers as desired. - </p> - - <p>Since naming Loggers after their owning class is such a common idiom, the convenience method - <code>LogManager.getLogger()</code> is provided to automatically use the calling class's fully - qualified class name as the Logger name. - </p> - - <p>Nevertheless, naming loggers after the class where they are - located seems to be the best strategy known so far. - </p> - <h4>LoggerConfig</h4> - <p> - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/config/LoggerConfig.html">LoggerConfig</a> - objects are created when Loggers are declared in the logging configuration. - The LoggerConfig contains a set of Filters that must allow the LogEvent to pass before it will be - passed to any Appenders. It contains references to the set of Appenders that should be used to - process the event. - </p> - <h5>Log Levels</h5> - <p>LoggerConfigs will be assigned a Log - <a href="../log4j-api/apidocs/org/apache/logging/log4j/Level.html">Level</a>. The set of built-in - levels includes TRACE, DEBUG, INFO, WARN, ERROR, and FATAL. Log4j 2 also supports - <a href="customloglevels.html">custom log levels</a>. - Another mechanism for getting more granularity is to use - <a href="../log4j-api/api.html#Markers">Markers</a> instead. - </p> - <p> - <a href="http://logging.apache.org/log4j/1.2/manual.html">Log4j 1.x</a> - and - <a href="http://logback.qos.ch/manual/architecture.html#effectiveLevel">Logback</a> - both have the concept of "Level Inheritance". In Log4j 2, Loggers and LoggerConfigs are two different - objects so this concept is implemented differently. Each Logger references the - appropriate LoggerConfig which in turn can reference its parent, thus achieving the same effect. - </p> - <p>Below are five tables with various assigned level values and the resulting levels that - will be associated with each Logger. Note that in all these cases if the root LoggerConfig - is not configured a default Level will be assigned to it. - </p> - - <table style="width: 40%"> - <caption align="bottom">Example 1</caption> - <tr> - <th>Logger Name</th> - <th>Assigned LoggerConfig</th> - <th>LoggerConfig Level</th> - <th>Logger Level</th> - </tr> - <tr> - <td>root</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X.Y</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X.Y.Z</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - </table> - - <p>In example 1 above, only the root logger is configured and has a Log Level. All the other - Loggers reference the root LoggerConfig and use its Level. - </p> - - <table style="width: 40%"> - <caption align="bottom">Example 2</caption> - <tr> - <th>Logger Name</th> - <th>Assigned LoggerConfig</th> - <th>LoggerConfig Level</th> - <th>Level</th> - </tr> - <tr> - <td>root</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y</td> - <td>X.Y</td> - <td>INFO</td> - <td>INFO</td> - </tr> - <tr> - <td>X.Y.Z</td> - <td>X.Y.Z</td> - <td>WARN</td> - <td>WARN</td> - </tr> - </table> - - <p>In example 2, all loggers have a configured LoggerConfig and obtain their Level - from it. - </p> - - <table style="width: 40%"> - <caption align="bottom">Example 3</caption> - <tr> - <th>Logger Name</th> - <th>Assigned LoggerConfig</th> - <th>LoggerConfig Level</th> - <th>Level</th> - </tr> - <tr> - <td>root</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y.Z</td> - <td>X.Y.Z</td> - <td>WARN</td> - <td>WARN</td> - </tr> - </table> - - <p>In example 3, the loggers<code>root</code>, - <code>X</code> - and - <code>X.Y.Z</code> - each have a configured LoggerConfig with the same name. The Logger - <code>X.Y</code> - does not have a configured LoggerConfig with a matching name so uses - the configuration of LoggerConfig - <code>X</code> - since that is the LoggerConfig whose - name has the longest match to the start of the Logger's name. - </p> - - <table style="width: 40%"> - <caption align="bottom">Example 4</caption> - <tr> - <th>Logger Name</th> - <th>Assigned LoggerConfig</th> - <th>LoggerConfig Level</th> - <th>level</th> - </tr> - <tr> - <td>root</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y.Z</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - </table> - - <p>In example 4, the loggers - <code>root</code> - and - <code>X</code> - each have a Configured - LoggerConfig with the same name. The loggers - <code>X.Y</code> - and - <code>X.Y.Z</code> - do not have configured LoggerConfigs and so get their Level from the LoggerConfig - assigned to them,<code>X</code>, since it is the LoggerConfig whose name has the - longest match to the start of the Logger's name. - </p> - - <table style="width: 40%"> - <caption align="bottom">Example 5</caption> - <tr> - <th>Logger Name</th> - <th>Assigned LoggerConfig</th> - <th>LoggerConfig Level</th> - <th>level</th> - </tr> - <tr> - <td>root</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y</td> - <td>X.Y</td> - <td>INFO</td> - <td>INFO</td> - </tr> - <tr> - <td>X.YZ</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - </table> - - <p>In example 5, the loggers<code>root</code>.<code>X</code>, and - <code>X.Y</code> - each - have a Configured LoggerConfig with the same name. The logger - <code>X.YZ</code> - does not have configured LoggerConfig and so gets its Level from the LoggerConfig - assigned to it,<code>X</code>, since it is the LoggerConfig whose name has the - longest match to the start of the Logger's name. It is not associated with LoggerConfig - <code>X.Y</code> - since tokens after periods must match exactly. - </p> - <table style="width: 40%"> - <caption align="bottom">Example 6</caption> - <tr> - <th>Logger Name</th> - <th>Assigned LoggerConfig</th> - <th>LoggerConfig Level</th> - <th>Level</th> - </tr> - <tr> - <td>root</td> - <td>root</td> - <td>DEBUG</td> - <td>DEBUG</td> - </tr> - <tr> - <td>X</td> - <td>X</td> - <td>ERROR</td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y</td> - <td>X.Y</td> - <td></td> - <td>ERROR</td> - </tr> - <tr> - <td>X.Y.Z</td> - <td>X.Y</td> - <td></td> - <td>ERROR</td> - </tr> - </table> - - <p>In example 6, LoggerConfig X.Y it has no configured level so it inherits its level - from LoggerConfig X. Logger X.Y.Z uses LoggerConfig X.Y since it doesn't have a LoggerConfig with - a name that exactly matches. It too inherits its logging level from LoggerConfig X. - </p> - - <p>The table below illustrates how Level filtering works. In the table, the vertical - header shows the Level of the LogEvent, while the horizontal header shows the Level associated - with the appropriate LoggerConfig. The intersection identifies whether the LogEvent would - be allowed to pass for further processing (Yes) or discarded (No). - </p> - <table> - <tr> - <th>Event Level</th> - <th style="text-align: center" colspan="6">LoggerConfig Level</th> - </tr> - <tr> - <th> </th> - <th>TRACE</th> - <th>DEBUG</th> - <th>INFO</th> - <th>WARN</th> - <th>ERROR</th> - <th>FATAL</th> - <th>OFF</th> - </tr> - <tr> - <th>ALL</th> - <td class="big-red">YES</td> - <td class="big-red">YES</td> - <td class="big-red">YES</td> - <td class="big-red">YES</td> - <td class="big-red">YES</td> - <td class="big-red">YES</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>TRACE</th> - <td class="big-green">YES</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>DEBUG</th> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>INFO</th> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>WARN</th> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>ERROR</th> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>FATAL</th> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-green">YES</td> - <td class="big-red">NO</td> - </tr> - <tr> - <th>OFF</th> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - <td class="big-red">NO</td> - </tr> - </table> - - <h4>Filter</h4> - <p>In addition to the automatic log Level filtering that takes place as described in the previous - section, Log4j provides - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/Filter.html">Filter</a>s that can - be applied before control is passed to any LoggerConfig, after control is passed to a LoggerConfig - but before calling any Appenders, after control is passed to a LoggerConfig but before calling a - specific Appender, and on each Appender. In a manner very similar to firewall filters, - each Filter can return one of three results, <code>Accept</code>, <code>Deny</code> or <code>Neutral</code>. - A response of <code>Accept</code> means that no other Filters should be called and the event should progress. - A response of <code>Deny</code> means the event should be immediately ignored and control should be returned - to the caller. A response of <code>Neutral</code> indicates the event should be passed to other Filters. If - there are no other Filters the event will be processed. - </p> - <p>Although an event may be accepted by a Filter the event still might not be logged. This can happen - when the event is accepted by the pre-LoggerConfig Filter but is then denied by a LoggerConfig - filter or is denied by all Appenders. - </p> - - <h4>Appender</h4> - - <p>The ability to selectively enable or disable logging requests based - on their logger is only part of the picture. Log4j allows logging - requests to print to multiple destinations. In log4j speak, an output - destination is called an - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/Appender.html">Appender</a>. - Currently, appenders exist for the console, files, remote socket servers, Apache Flume, - JMS, remote UNIX Syslog daemons, and various database APIs. See the section on - <a href="appenders.html">Appenders</a> for more details on the various types available. - More than one Appender can be attached to a Logger. - </p> - <p>An Appender can be added to a Logger by calling the - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/config/Configuration.html#addLoggerAppender(org.apache.logging.log4j.core.Logger,%20org.apache.logging.log4j.core.Appender)">addLoggerAppender</a> - method of the current Configuration. If a LoggerConfig matching the name of the Logger does - not exist, one will be created, the Appender will be attached to it and then all Loggers - will be notified to update their LoggerConfig references. - </p> - <p><b>Each enabled logging request for a given logger will be forwarded to all the appenders in - that Logger's LoggerConfig as well as the Appenders of the LoggerConfig's parents.</b> In - other words, Appenders are inherited additively from the LoggerConfig hierarchy. For example, - if a console appender is added to the root logger, then all enabled logging requests will at - least print on the console. If in addition a file appender is added to a LoggerConfig, say - <em>C</em>, then enabled logging requests for <em>C</em> and <em>C</em>'s children will print - in a file <em>and</em> on the console. It is possible to override this default behavior so that - Appender accumulation is no longer additive by setting <code>additivity="false"</code> on the - Logger declaration in the configuration file. - </p> - <p>The rules governing appender additivity are summarized below.</p> - - <div class="well"> - <dl> - <dt><b>Appender Additivity</b></dt> - <dd> - <p> - The output of a log statement of Logger <i>L</i> will go to all the Appenders in the LoggerConfig - associated with <i>L</i> and the ancestors of that LoggerConfig. This is the meaning of the term - "appender additivity". - </p> - <p> - However, if an ancestor of the LoggerConfig associated with Logger <i>L</i>, say <i>P</i>, has the - additivity flag set to <code>false</code>, then <i>L</i>'s output will be directed to all the - appenders in <i>L</i>'s LoggerConfig and it's ancestors up to and including <i>P</i> but not the - Appenders in any of the ancestors of <i>P</i>. - </p> - <p>Loggers have their additivity flag set to <code>true</code> by default.</p> - </dd> - </dl> - </div> - - <p>The table below shows an example:</p> - - <table> - <tr> - <th>Logger<br />Name </th> - <th>Added<br/>Appenders</th> - <th>Additivity<br/>Flag</th> - <th>Output Targets</th> - <th>Comment</th> - </tr> - <tr> - <td>root</td> - <td>A1</td> - <td>not applicable</td> - <td>A1</td> - <td>The root logger has no parent so additivity does not apply to it.</td> - </tr> - <tr> - <td>x</td> - <td>A-x1, A-x2</td> - <td>true </td> - <td>A1, A-x1, A-x2</td> - <td>Appenders of "x" and root.</td> - </tr> - <tr> - <td>x.y</td> - <td>none</td> - <td>true </td> - <td>A1, A-x1, A-x2</td> - <td>Appenders of "x" and root. It would not be typical to configure a Logger with no Appenders.</td> - </tr> - <tr> - <td>x.y.z</td> - <td>A-xyz1</td> - <td>true </td> - <td>A1, A-x1, A-x2, A-xyz1</td> - <td>Appenders in "x.y.z", "x" and root.</td> - </tr> - <tr> - <td>security</td> - <td>A-sec</td> - <td><font color="blue">false</font></td> - <td>A-sec</td> - <td>No appender accumulation since the additivity flag is set to <code>false</code>.</td> - </tr> - <tr> - <td>security.access</td> - <td>none</td> - <td>true</td> - <td>A-sec</td> - <td>Only appenders of "security" because the additivity flag in "security" is - set to <code>false</code>. - </td> - </tr> - </table> - - <h4>Layout</h4> - <p>More often than not, users wish to customize not only the output destination but also the output format. - This is accomplished by associating a - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/Layout.html">Layout</a> - with an Appender. The Layout is responsible for formatting the LogEvent according to the user's - wishes, whereas an appender takes care of sending the formatted output to its destination. - The <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/layout/PatternLayout.html">PatternLayout</a>, - part of the standard log4j distribution, lets the user specify the output - format according to conversion patterns similar to the C language <code>printf</code> function. - </p> - - <p>For example, the PatternLayout with the conversion pattern "%r [%t] - %-5p %c - %m%n" will output something akin to: - </p> - <pre>176 [main] INFO org.foo.Bar - Located nearest gas station.</pre> - - <p>The first field is the number of milliseconds elapsed since the - start of the program. The second field is the thread making the log - request. The third field is the level of the log statement. The - fourth field is the name of the logger associated with the log - request. The text after the '-' is the message of the statement. - </p> - - <p>Log4j comes with many different <a href="layouts.html">Layouts</a> for various use cases such as - JSON, XML, HTML, and Syslog (including the new RFC 5424 version). Other appenders such as the - database connectors fill in specified fields instead of a particular textual layout. - </p> - - <p>Just as importantly, log4j will render the content of the log - message according to user specified criteria. For example, if you - frequently need to log <code>Oranges</code>, an object type used in - your current project, then you can create an OrangeMessage that accepts an - Orange instance and pass that to Log4j so that the Orange object can - be formatted into an appropriate byte array when required. - </p> - - <h4>StrSubstitutor and StrLookup</h4> - <p>The - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrSubstitutor.html"> - StrSubstitutor - </a> - class and - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrLookup.html">StrLookup</a> - interface were borrowed from - <a href="https://commons.apache.org/proper/commons-lang/">Apache Commons Lang</a> and then modified - to support evaluating LogEvents. In addition the - <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/Interpolator.html">Interpolator</a> - class was borrowed from Apache Commons Configuration to allow the StrSubstitutor to evaluate variables - that from multiple StrLookups. It too was modified to support evaluating LogEvents. Together these - provide a mechanism to allow the configuration to reference variables coming from System Properties, - the configuration file, the ThreadContext Map, StructuredData in the LogEvent. The variables can - either be resolved when the configuration is processed or as each event is processed, if the component - is capable of handling it. See - <a href="lookups.html">Lookups</a> - for more information. - </p> - - </subsection> - - </section> - </body> -</document>