This is an automated email from the ASF dual-hosted git repository.

vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git

commit 34eb9f036e853c7d4b05bfd9e36e2e170a12087e
Author: Volkan Yazıcı <[email protected]>
AuthorDate: Tue Jun 25 10:25:03 2024 +0200

    Rewrite architecture page and several other affected pages
---
 .../manual/customloglevels/custom/log4j2.json      |   34 +
 .../customloglevels/custom/log4j2.properties       |   30 +
 .../manual/customloglevels/custom/log4j2.xml       |   28 +
 .../manual/customloglevels/custom/log4j2.yaml      |   37 +
 .../manual/customloglevels/filtering/log4j2.json   |   24 +
 .../customloglevels/filtering/log4j2.properties    |   24 +
 .../manual/customloglevels/filtering/log4j2.xml    |   21 +
 .../manual/customloglevels/filtering/log4j2.yaml   |   31 +
 .../manual/customloglevels/filtering/logback.xml   |   34 +
 .../antora/modules/ROOT/images/Log4jClasses.jpg    |  Bin 31443 -> 0 bytes
 .../modules/ROOT/pages/manual/architecture.adoc    | 1162 +++++++++++++-------
 .../modules/ROOT/pages/manual/configuration.adoc   |    2 +-
 .../modules/ROOT/pages/manual/customloglevels.adoc |  170 +--
 .../modules/ROOT/pages/manual/extending.adoc       |    4 +-
 .../antora/modules/ROOT/pages/manual/markers.adoc  |    6 +-
 15 files changed, 1117 insertions(+), 490 deletions(-)

diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.json
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.json
new file mode 100644
index 0000000000..06be7e3bcd
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.json
@@ -0,0 +1,34 @@
+{
+  "Configuration": {
+    "Appenders": {
+      "Console": {
+        "name": "CONSOLE",
+        "PatternLayout": {}
+      },
+      "File": {
+        "name": "FILE",
+        "JsonTemplateLayout": {}
+      }
+    },
+    "CustomLevels": [
+      { //<1>
+        "name": "VERBOSE",
+        "intLevel": 550
+      }
+    ],
+    "Loggers": {
+      "Root": {
+        "level": "ALL",
+        "AppenderRef": [
+          {
+            "ref": "CONSOLE",
+            "level": "VERBOSE" //<2>
+          },
+          {
+            "ref": "FILE"
+          }
+        ]
+      }
+    }
+  }
+}
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.properties
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.properties
new file mode 100644
index 0000000000..6033c0851d
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.properties
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+appender.0.type = Console
+appender.0.name = CONSOLE
+appender.0.layout.type = JsonTemplateLayout
+appender.1.type = File
+appender.1.name = FILE
+appender.1.layout.type = PatternLayout
+
+customLevel.0.name = VERBOSE #<1>
+customLevel.0.intLevel = 550
+
+rootLogger.level = ALL
+rootLogger.appenderRef.0.ref = CONSOLE
+rootLogger.appenderRef.0.level = VERBOSE #<2>
+rootLogger.appenderRef.1.ref = FILE
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.xml
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.xml
new file mode 100644
index 0000000000..357d197932
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+               xmlns="https://logging.apache.org/xml/ns";
+               xsi:schemaLocation="
+                       https://logging.apache.org/xml/ns
+                       https://logging.apache.org/xml/ns/log4j-config-2.xsd";>
+
+  <Appenders>
+    <Console name="CONSOLE">
+      <PatternLayout/>
+    </Console>
+    <File name="FILE" fileName="logs/app.log">
+      <JsonTemplateLayout/>
+    </File>
+  </Appenders>
+
+  <CustomLevels>
+    <CustomLevel name="VERBOSE" intLevel="550"/> <!--1-->
+  </CustomLevels>
+
+  <Loggers>
+    <Root level="ALL">
+      <AppenderRef ref="CONSOLE" level="VERBOSE"/> <!--2-->
+      <AppenderRef ref="FILE"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.yaml
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.yaml
new file mode 100644
index 0000000000..d702f4490d
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/custom/log4j2.yaml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+Configuration:
+
+  Appenders:
+    Console:
+      name: "CONSOLE"
+      PatternLayout: {}
+    File:
+      name: "FILE"
+      JsonTemplateLayout: {}
+
+  CustomLevels: #<1>
+    - name: "VERBOSE"
+      intLevel: 550
+
+  Loggers:
+    Root:
+      level: "ALL"
+      AppenderRef:
+        - ref: "CONSOLE"
+          level: "VERBOSE" #<2>
+        - ref: "FILE"
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.json
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.json
new file mode 100644
index 0000000000..14f24253fc
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.json
@@ -0,0 +1,24 @@
+{
+  "Configuration": {
+    "Appenders": {
+      "Console": {
+        "name": "CONSOLE",
+        "JsonTemplateLayout": {}
+      }
+    },
+    "Loggers": {
+      "Logger": [
+        {
+          "name": "com.mycompany",
+          "level": "INFO" //<1>
+        }
+      ],
+      "Root": {
+        "level": "ERROR", //<2>
+        "AppenderRef": {
+          "ref": "CONSOLE"
+        }
+      }
+    }
+  }
+}
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.properties
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.properties
new file mode 100644
index 0000000000..a2d008872e
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.properties
@@ -0,0 +1,24 @@
+#
+# 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.
+#
+appender.0.type = Console
+appender.0.name = CONSOLE
+appender.0.layout.type = JsonTemplateLayout
+
+logger.0.name = com.mycompany
+logger.0.level = INFO #<1>
+rootLogger.level = ERROR #<2>
+rootLogger.appenderRef.0.ref = CONSOLE
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.xml
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.xml
new file mode 100644
index 0000000000..bc5d5bb726
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+               xmlns="https://logging.apache.org/xml/ns";
+               xsi:schemaLocation="
+                       https://logging.apache.org/xml/ns
+                       https://logging.apache.org/xml/ns/log4j-config-2.xsd";>
+
+  <Appenders>
+    <Console name="CONSOLE">
+      <JsonTemplateLayout/>
+    </Console>
+  </Appenders>
+
+  <Loggers>
+    <Logger name="com.mycompany" level="INFO"/> <!--1-->
+    <Root level="ERROR"> <!--2-->
+      <AppenderRef ref="CONSOLE"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.yaml
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.yaml
new file mode 100644
index 0000000000..8b7d3ce2c0
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/log4j2.yaml
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+Configuration:
+
+  Appenders:
+    Console:
+      name: "CONSOLE"
+      JsonTemplateLayout: {}
+
+  Loggers:
+    Logger:
+      - name: "com.mycompany"
+        level: "INFO" #<1>
+    Root:
+      level: "ERROR" #<2>
+      AppenderRef:
+        ref: "CONSOLE"
diff --git 
a/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/logback.xml
 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/logback.xml
new file mode 100644
index 0000000000..09491b9571
--- /dev/null
+++ 
b/src/site/antora/modules/ROOT/examples/manual/customloglevels/filtering/logback.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<!DOCTYPE configuration>
+<configuration>
+
+  <import class="ch.qos.logback.core.ConsoleAppender"/>
+
+  <appender name="CONSOLE" class="ConsoleAppender">
+    <encoder class="PatternLayoutEncoder">
+      <pattern><![CDATA[%d %5p [%t] %c{1} -- %m%n]]></pattern>
+    </encoder>
+  </appender>
+
+  <logger name="com.mycompany" level="INFO"/>
+  <root level="ERROR">
+    <appender-ref ref="CONSOLE"/>
+  </root>
+
+</configuration>
diff --git a/src/site/antora/modules/ROOT/images/Log4jClasses.jpg 
b/src/site/antora/modules/ROOT/images/Log4jClasses.jpg
deleted file mode 100755
index ea16084bd6..0000000000
Binary files a/src/site/antora/modules/ROOT/images/Log4jClasses.jpg and 
/dev/null differ
diff --git a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc 
b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
index f151b79081..91213fec00 100644
--- a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
@@ -16,469 +16,789 @@
 ////
 = Architecture
 
-== Main Components
-
-Log4j uses the classes shown in the diagram below.
-
-image: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 deliver the LogEvents.
-
-[id=logger-hierarchy]
-=== 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:../javadoc/log4j-api/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
-xref:manual/api.adoc[Log4j API].
-
-[#logger-context]
-=== LoggerContext
+Log4j Core is the reference implementation of xref:manual/api.adoc[] and 
composed of several components.
+In this section we will try to explain major pillars its architecture stands 
on.
+An overview these major classes can be depicted as follows:
+
+[#architecture-diagram]
+.An overview of major classes and their relation
+[plantuml]
+....
+@startuml
+
+class LoggerContext {
+  Configuration config
+  Logger[] loggers
+  Logger getLogger(String name)
+}
+
+note left of LoggerContext {
+  Anchor for the logging system
+}
+
+LoggerContext --> Configuration
+
+LoggerContext --> "0..*" Logger
+
+class Configuration {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
+
+note left of Configuration
+  Encapsulates components compiled
+  from a user-provided configuration
+  file (e.g., `log4j2.xml`)
+end note
+
+Configuration --> "0..*" Filter
+
+Configuration --> "0..*" Appender
+
+Configuration --> "0..*" LoggerConfig
+
+Configuration --> StrSubstitutor
+
+class Appender {
+  Layout layout
+  void append(LogEvent)
+}
+
+Appender -[#green,thickness=6]-> Layout
+
+class Layout {
+  byte[] encode(LogEvent)
+}
+
+class Filter {
+  Result filter(LogEvent)
+}
+
+note right of Filter
+  Note that a `Filter` can
+  be provided at 4 levels:
+  1. `Configuration`
+  2. `LoggerConfig`
+  3. `AppenderRef`
+  4. `AppenderControl`
+end note
+
+class LoggerConfig {
+  AppenderRef[] appenderRefs
+  AppenderControl[] appenderControls
+  Level level
+  Filter filter
+  void log(LogEvent)
+}
+
+LoggerConfig --> "0..*" AppenderRef
+
+LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
+
+LoggerConfig --> Filter
+
+class AppenderRef {
+  String appenderName
+  Level level
+  Filter filter
+}
+
+note right of AppenderRef
+  Denotes a user-provided
+  appender configuration
+  for a `Logger`,
+  e.g., `<AppenderRef`
+  element in a `log4j2.xml`.
+
+  It is used to populate
+  `AppenderControl`s.
+end note
+
+AppenderRef --> Filter
+
+class AppenderControl {
+  Appender appender
+  Filter filter
+  void append(LogEvent)
+}
+
+note right of AppenderControl
+  Decorates an `Appender`
+  with a `Filter`
+end note
+
+AppenderControl -[#green,thickness=6]-> Appender
+
+AppenderControl --> Filter
+
+class StrSubstitutor {
+  Interpolator interpolator
+  String replace(String input)
+}
+
+note right of StrSubstitutor
+  Responsible for
+  property substitution
+  (e.g., `${env:USER}`)
+end note
+
+StrSubstitutor --> Interpolator
+
+class Interpolator {
+  StrLookup[] lookups
+  String lookup(String input)
+}
+
+Interpolator --> "0..*" StrLookup
+
+class StrLookup {
+  String lookup(String input)
+}
+
+class Logger {
+  void log(Level level, Message message)
+}
+
+note right of Logger
+  The main API entry point
+  users interact with
+end note
+
+Logger -[#green,thickness=6]-> LoggerConfig : delegates `log()`
+
+@enduml
+....
+
+At a really high level,
+
+* A <<LoggerContext>>, the composition anchor, gets created in combination 
with a <<Configuration>>.
+Both can be created either directly (i.e., programmatically) or indirectly at 
first interaction with Log4j.
+* `LoggerContext` creates <<Logger>>s that users interact with for logging 
purposes.
+* <<Appender>> delivers a 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/LogEvent.html[`LogEvent`]
 to a target (file, socket, database, etc.) and typically uses a <<Layout>> to 
encode log events.
+* <<LoggerConfig>> encapsulates configuration for a `Logger`, as 
`AppenderControl` and `AppenderRef` for ``Appender``s.
+* <<Configuration>> is equipped with <<StrSubstitutor>> to allow property 
substitution in `String`-typed values.
+* A typical `log()` call triggers a chain of invocations through classes 
`Logger`, `LoggerConfig`, `AppenderControl`, `Appender`, and `Layout` in order 
– this is depicted using green arrows in 
xref:architecture-diagram[xrefstyle=short].
+
+Following sections examine this interplay in detail.
+
+[#LoggerContext]
+== `LoggerContext`
 
 The 
link:../javadoc/log4j-api/org/apache/logging/log4j/spi/LoggerContext.html[`LoggerContext`]
 acts as the anchor point for the logging system.
-It is primarily responsible for instantiating <<logger>>s.
+It is associated with an active <<Configuration>> and is primarily responsible 
for instantiating <<Logger>>s.
+
+[#LoggerContext-diagram]
+.`LoggerContext` and other directly related classes
+[plantuml]
+....
+@startuml
+
+class LoggerContext #line.bold {
+  Configuration config
+  Logger[] loggers
+  Logger getLogger(String name)
+}
+
+LoggerContext --> Configuration
+
+LoggerContext --> "0..*" Logger
+
+class Configuration {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
+
+class Logger {
+  void log(Level level, Message message)
+}
+
+@enduml
+....
 
 In most cases, applications have a single global `LoggerContext`.
 Though in certain cases (e.g., Java EE applications), Log4j can be configured 
to accommodate multiple ``LoggerContext``s.
 Refer to xref:manual/logsep.adoc[] for details.
 
-=== Configuration
-
-Every LoggerContext has an active
-link:../javadoc/log4j-core/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]
-=== Logger
-
-As stated previously, Loggers are created by calling
-link:../javadoc/log4j-api/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:../javadoc/log4j-api/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 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 xref:manual/configuration.adoc[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]
-=== LoggerConfig
-
-link:../javadoc/log4j-core/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:../javadoc/log4j-api/org/apache/logging/log4j/Level.html[`Level`].
-The set of built-in levels includes ALL, TRACE, DEBUG, INFO, WARN, ERROR,
-FATAL, and OFF. Log4j 2 also supports xref:manual/customloglevels.adoc[custom 
log
-levels]. Another mechanism for getting more granularity is to use
-xref:manual/markers.adoc[markers] instead. The OFF and ALL
-levels are not intended to be used on calls to the logging API.
-Specifying OFF in the configuration implies no logging events should
-match while specifying ALL would mean all events match, including custom
-events. However, OFF can be used on logging API calls in special cases
-where the event should always be logged regardless of the configuration.
-However, it is generally recommended that a Marker with a corresponding
-global Marker Filter be used instead.
-
-{logging-services-url}/log4j/1.x/manual.html[Log4j 1] and
-{logback-url}/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
+[#Configuration]
+== `Configuration`
+
+Every <<LoggerContext>> is associated with an active 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`].
+It models the configuration of all appenders, layouts, filters, loggers, and 
contains the reference to <<StrSubstitutor>>.
+
+[#Configuration-diagram]
+.`Configuration` and other directly related classes
+[plantuml]
+....
+@startuml
+
+class LoggerContext {
+  Configuration config
+  Logger[] loggers
+  Logger getLogger(String name)
+}
+
+LoggerContext --> Configuration
+
+class Configuration #line.bold {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
+
+Configuration --> "0..*" Filter
+
+Configuration --> "0..*" Appender
+
+Configuration --> "0..*" LoggerConfig
+
+Configuration --> StrSubstitutor
+
+class Appender {
+  Layout layout
+  void append(LogEvent)
+}
+
+class Filter {
+  Result filter(LogEvent)
+}
+
+class LoggerConfig {
+  AppenderRef[] appenderRefs
+  AppenderControl[] appenderControls
+  Level level
+  Filter filter
+  void log(LogEvent)
+}
+
+class StrSubstitutor {
+  Interpolator interpolator
+  String replace(String input)
+}
+@enduml
+....
+
+During reconfiguration, two `Configuration` instances will be present.
+Once all ``Logger``s have been redirected to the new `Configuration`, the old 
one will be stopped and discarded.
+
+Configuration of Log4j Core is typically done at application initialization.
+The preferred way is by reading a xref:manual/configuration.adoc[configuration 
file], but it can also be done xref:manual/customconfig.adoc[programmatically].
+This is further discussed in xref:manual/config-intro.adoc[].
+
+[#Logger]
+== `Logger`
+
+link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[`Logger`]s are 
the primary user entry point for logging.
+They are created by calling one of the `getLogger()` methods of 
link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html[`LogManager`]
 – this is further documented in xref:manual/api.adoc[].
+The `Logger` itself performs no direct actions.
+It simply has a name and is associated with a <<LoggerConfig>>.
+
+[#Logger-diagram]
+.`Logger` and other directly related classes
+[plantuml]
+....
+@startuml
+
+class LoggerContext {
+  Configuration config
+  Logger[] loggers
+  Logger getLogger(String name)
+}
+
+LoggerContext --> "0..*" Logger
+
+class LoggerConfig {
+  AppenderRef[] appenderRefs
+  AppenderControl[] appenderControls
+  Level level
+  Filter filter
+  void log(LogEvent)
+}
+
+class Logger #line.bold {
+  void log(Level level, Message message)
+}
+
+Logger -[#green,thickness=6]-> LoggerConfig : delegates `log()`
+
+@enduml
+....
+
+The hierarchy between <<LoggerConfig>>s, implies the very same hierarchy 
between ``Logger``s too.
+You can use `LogManager.getRootLogger()` to get the root logger.
+Note that Log4j API has no assumptions on a `Logger` hierarchy – this is a 
feature implemented by Log4j Core.
+
+When the <<Configuration>> is modified, ``Logger``s may become associated with 
a different `LoggerConfig`, thus causing their behavior to be modified.
+Refer to xref:manual/configuration.adoc#configuring-loggers[configuring 
``Logger``s] for further information.
+
+[#LoggerConfig]
+== `LoggerConfig`
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/LoggerConfig.html[`LoggerConfig`]
 binds <<Logger>> definitions to their associated components (appenders, 
filters, etc.) as declared in the active <<Configuration>>.
+The details of mapping a `Configuration` to ``LoggerConfig``s is explained 
xref:manual/configuration.adoc#configuring-loggers[here].
+``Logger``s effectively interact with appenders, filters, etc. through 
corresponding ``LoggerConfig``s.
+A `LoggerConfig` essentially contains
+
+* A reference to its parent (except if it is the root logger)
+* A xref:manual/customloglevels.adoc[level] denoting the severity of messages 
that are accepted (defaults to `ERROR`)
+* <<Filter>>s that must allow the `LogEvent` to pass before it will be passed 
to any <<Appender>>s
+* References to <<Appender>>s that should be used to process the event
+
+[#LoggerConfig-diagram]
+.`LoggerConfig` and other directly related classes
+[plantuml]
+....
+@startuml
+
+class Configuration {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
+
+Configuration --> "0..*" LoggerConfig
+
+class Filter {
+  Result filter(LogEvent)
+}
+
+class LoggerConfig #line.bold {
+  AppenderRef[] appenderRefs
+  AppenderControl[] appenderControls
+  Level level
+  Filter filter
+  void log(LogEvent)
+}
+
+LoggerConfig --> "0..*" AppenderRef
+
+LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
+
+LoggerConfig --> Filter
+
+class AppenderRef {
+  String appenderName
+  Level level
+  Filter filter
+}
+
+class AppenderControl {
+  Appender appender
+  Filter filter
+  void append(LogEvent)
+}
+
+class Logger {
+  void log(Level level, Message message)
+}
+
+Logger -[#green,thickness=6]-> LoggerConfig : delegates `log()`
+
+@enduml
+....
+
+[#logger-hiearchy]
+=== Logger hierarchy
+
+Log4j Core has a *hierarchical* model of ``LoggerConfig``s, and hence 
``Logger``s.
+A `LoggerConfig` called `child` is said to be parented by `parent`, if 
`parent` has the _longest prefix match_ on name.
+This match is case-sensitive and performed after tokenizing the name by 
splitting it from `.` (dot) characters.
+For a positive name match, tokens must match exhaustively.
+See xref:#logger-hiearchy-diagram[xrefstyle=short] for an example.
+
+[#logger-hiearchy-diagram]
+.Example hierarchy of loggers named `X`, `X.Y`, `X.Y.Z`, and `X.YZ`
+[plantuml]
+....
+@startmindmap
+* root
+** X
+*** X.Y
+**** X.Y.Z
+*** X.YZ
+@endmindmap
+....
+
+If a `LoggerConfig` is not provided an explicit level, it will be inherited 
from its parent.
+Similarly, if a user programmatically requests a `Logger` with a name that 
doesn't have a directly corresponding `LoggerConfig` configuration entry with 
its name, the `LoggerConfig` of the parent will be used.
+
+.Click for examples on `LoggerConfig` hierarchy
+[%collapsible]
+====
+Below we demonstrate the `LoggerConfig` hierarchy by means of _level 
inheritance_.
+That is, we will examine the effective level of a `Logger` in various 
`LoggerConfig` settings.
+
+.Only the root logger is configured with a level, and it is `DEBUG`
+[%header,cols="1m,1m,1m,1m"]
+|===
+|Logger name |Assigned `LoggerConfig` name |Configured level |Effective 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
+|X |root | |DEBUG
+|X.Y |root | |DEBUG
+|X.Y.Z |root | |DEBUG
+|===
+
+.All loggers are configured with a level
+[%header,cols="1m,1m,1m,1m"]
+|===
+|Logger name |Assigned `LoggerConfig` |Configured level |Effective 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
+.All loggers are configured with a level, except the logger `X.Y`
+[%header,cols="1m,1m,1m,1m"]
+|===
+|Logger name |Assigned `LoggerConfig` |Configured level |Effective level
 |root |root |DEBUG |DEBUG
 |X |X |ERROR |ERROR
-|X.Y |X |ERROR |ERROR
+|X.Y |X | |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
-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
+|===
+
+.All loggers are configured with a level, except loggers `X.Y` and `X.Y.Z`
+[%header,cols="1m,1m,1m,1m"]
+|===
+|Logger name |Assigned `LoggerConfig` |Configured level |Effective 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 has 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"]
+|X.Y |X | |ERROR
+|X.Y.Z |X | |ERROR
+|===
+
+.All loggers are configured with a level, except the logger `X.YZ`
+[%header,cols="1m,1m,1m,1m"]
 |===
-|Logger Name |Assigned LoggerConfig |LoggerConfig Level |Level
+|Logger name |Assigned `LoggerConfig` |Configured level |Effective level
 |root |root |DEBUG |DEBUG
 |X |X |ERROR |ERROR
-|X.Y |X.Y | |ERROR
-|X.Y.Z |X.Y | |ERROR
+|X.Y |X.Y |INFO |INFO
+|X.YZ |X | |ERROR
 |===
+====
 
-In example 6, LoggerConfig X.Y 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.
+For further information on log levels and using them for filtering purposes in 
a configuration, see xref:manual/customloglevels.adoc[].
 
-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).
+[#Filter]
+== `Filter`
 
-[cols=8*,options="header"]
-|===
-|Event Level
-7+|LoggerConfig Level
+In addition to <<LoggerConfig,the level-based filtering facilitated by 
`LoggerConfig`>>, Log4j provides 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/Filter.html[`Filter`]s 
to evaluate the parameters of a logging call (i.e., context-wide filter) or a 
log event, and decide if it should be processed further in the pipeline.
 
-|  |`TRACE` |`DEBUG` |`INFO` |`WARN` |`ERROR` |`FATAL` |`OFF`
+[#Filter-diagram]
+.`Filter` and other directly related classes
+[plantuml]
+....
+@startuml
 
-|`ALL` |❌ |❌ |❌ |❌ |❌ |❌ |❌
+class Configuration {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
 
-|`TRACE` |✅ |❌ |❌ |❌ |❌ |❌ |❌
+Configuration --> "0..*" Filter
 
-|`DEBUG` |✅ |✅ |❌ |❌ |❌ |❌ |❌
+Configuration --> "0..*" LoggerConfig
 
-|`INFO` |✅ |✅ |✅ |❌ |❌ |❌ |❌
+class Filter #line.bold {
+  Result filter(LogEvent)
+}
 
-|`WARN` |✅ |✅ |✅ |✅ |❌ |❌ |❌
+class LoggerConfig {
+  AppenderRef[] appenderRefs
+  AppenderControl[] appenderControls
+  Level level
+  Filter filter
+  void log(LogEvent)
+}
 
-|`ERROR` |✅ |✅ |✅ |✅ |✅ |❌ |❌
+LoggerConfig --> "0..*" AppenderRef
 
-|`FATAL` |✅ |✅ |✅ |✅ |✅ |✅ |❌
+LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
 
-|`OFF` |✅ |✅ |✅ |✅ |✅ |✅ |✅
-|===
+LoggerConfig --> Filter
+
+class AppenderRef {
+  String appenderName
+  Level level
+  Filter filter
+}
+
+AppenderRef --> Filter
+
+AppenderControl --> Filter
+
+@enduml
+....
+
+Refer to xref:manual/filters.adoc[] for further information.
+
+[#Appender]
+== `Appender`
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html[`Appender`]s
 are responsible for delivering a 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/LogEvent.html[`LogEvent`]
 to a certain target; console, file, database, etc.
+While doing so, they typically use <<Layout>>s to encode the log event.
+See xref:manual/appenders.adoc[] for the complete guide.
+
+[#Appender-diagram]
+.`Appender` and other directly related classes
+[plantuml]
+....
+@startuml
+
+class Configuration {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
 
-=== Filter
-
-In addition to the automatic log Level filtering that takes place as
-described in the previous section, Log4j provides
-link:../javadoc/log4j-core/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:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html[`Appender`].
-Currently, appenders exist for the console, files, remote socket
-servers, Apache Flume, remote UNIX Syslog daemons, and various
-database APIs. See the section on xref:manual/appenders.adoc[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:../javadoc/log4j-core/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, and 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:
+Configuration --> "0..*" Filter
 
+Configuration --> "0..*" Appender
+
+Configuration --> "0..*" LoggerConfig
+
+class Appender #line.bold {
+  Layout layout
+  void append(LogEvent)
+}
+
+Appender -[#green,thickness=6]-> Layout
+
+class Layout {
+  byte[] encode(LogEvent)
+}
+
+class Filter {
+  Result filter(LogEvent)
+}
+
+class LoggerConfig {
+  AppenderRef[] appenderRefs
+  AppenderControl[] appenderControls
+  Level level
+  Filter filter
+  void log(LogEvent)
+}
+
+LoggerConfig --> "0..*" AppenderRef
+
+LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
+
+LoggerConfig --> Filter
+
+class AppenderRef {
+  String appenderName
+  Level level
+  Filter filter
+}
+
+AppenderRef --> Filter
+
+class AppenderControl {
+  Appender appender
+  Filter filter
+  void append(LogEvent)
+}
+
+AppenderControl -[#green,thickness=6]-> Appender
+
+AppenderControl --> Filter
+
+@enduml
+....
+
+An `Appender` can be added to a <<Logger>> by calling the 
link:../javadoc/log4j-core/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, and the `Appender` will be  attached to it, and then all 
``Logger``s will be notified to update their `LoggerConfig` references.
+
+[#appender-additivity]
+=== Appender additivity
+
+Each enabled logging request for a given logger will be forwarded to all the 
appenders in the corresponding ``Logger``'s `LoggerConfig`, as well as to the 
``Appender``s of the ``LoggerConfig``'s parents.
+In other words, ``Appender``s 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 `LC`, then 
enabled logging requests for `LC` and ``LC``'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` attribute to `false` on 
xref:manual/configuration.adoc#configuring-loggers[the `Logger` declaration in 
the configuration file].
+
+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`.
+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`.
+
+.Click for an example on appender additivity
+[%collapsible]
+====
+[#appender-additivity-diagram]
+.Example hierarchy of logger configurations to demonstrate appender additivity
+[plantuml]
+....
+@startmindmap
+* root
+** A
+*** A.B1 (additivity=false)
+**** A.B1.C
+***** A.B1.C.D
+*** A.B2.C
+**** A.B2.C.D (additivity=false)
+@endmindmap
+....
+
+In xref:#appender-additivity-diagram[xrefstyle=short], the effective appenders 
for each logger configuration are as follows:
+
+.Effective appenders of logger configurations in 
xref:#appender-additivity-diagram[xrefstyle=short]
+[cols="1c,1c,1c,1c,1c,1c,1c"]
 |===
-|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`.
+.2+^.^h| Appender
+6+^.h|Logger configuration
+
+| `A`
+| `A.B1`
+| `A.B1.C`
+| `A.B1.C.D`
+| `A.B2.C`
+| `A.B2.C.D`
+
+| `root`
+| ✅
+| ✅
+| ✅
+| ✅
+| ✅
+| ❌
+
+| `A`
+| ✅
+| ❌
+| ❌
+| ❌
+| ✅
+| ❌
+
+| `A.B1`
+| -
+| ✅
+| ✅
+| ✅
+| -
+| -
+
+| `A.B1.C`
+| -
+| -
+| ✅
+| ✅
+| -
+| -
+
+| `A.B1.C.D`
+| -
+| -
+| -
+| ✅
+| -
+| -
+
+| `A.B2.C`
+| -
+| -
+| -
+| -
+| ✅
+| ❌
+
+| `A.B2.C.D`
+| -
+| -
+| -
+| -
+| -
+| ✅
 |===
+====
+
+[#Layout]
+== `Layout`
 
-=== Layout
+An <<Appender>> uses a *layout* to encode a 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/LogEvent.html[`LogEvent`]
 into a form that meets the needs of whatever will be consuming the log event.
 
-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:../javadoc/log4j-core/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:../javadoc/log4j-core/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.
+[#Layout-diagram]
+.`Layout` and other directly related classes
+[plantuml]
+....
+@startuml
 
-For example, the PatternLayout with the conversion pattern "%r [%t] %-5p
-%c - %m%n" will output something akin to:
+class Appender {
+  Layout layout
+  void append(LogEvent)
+}
 
+Appender -[#green,thickness=6]-> Layout
+
+class Layout #line.bold {
+  byte[] encode(LogEvent)
+}
+
+@enduml
 ....
-176 [main] INFO  org.foo.Bar - Located nearest gas station.
+
+Refer to xref:manual/layouts.adoc[] for details.
+
+[#StrSubstitutor]
+== `StrSubstitutor` et al.
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrSubstitutor.html[`StrSubstitutor`]
 is a `String` interpolation tool that can be used in both configurations and 
components (e.g., appenders, layouts).
+It accepts an 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/Interpolator.html[`Interpolator`]
 to determine if a key maps to a certain value.
+`Interpolator` is essentially a facade delegating to multiple 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html[`StrLookup`]
 (aka. _lookup_) implementations.
+
+[#StrSubstitutor-diagram]
+.`StrSubstitutor` et al. and other directly related classes
+[plantuml]
+....
+@startuml
+
+class Configuration {
+  Appender[] appenders
+  Filter[] filters
+  LoggerConfig[] loggerConfigs
+  LoggerConfig getLoggerConfig(String name)
+  StrSubstitutor substitutor
+}
+
+Configuration --> StrSubstitutor
+
+class StrSubstitutor #line.bold {
+  Interpolator interpolator
+  String replace(String input)
+}
+
+StrSubstitutor --> Interpolator
+
+class Interpolator {
+  StrLookup[] lookups
+  String lookup(String input)
+}
+
+Interpolator --> "0..*" StrLookup
+
+class StrLookup {
+  String lookup(String input)
+}
+
+@enduml
 ....
 
-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 xref:manual/layouts.adoc[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:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrSubstitutor.html[`StrSubstitutor`]
-class and
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html[`StrLookup`]
-interface was borrowed from
-https://commons.apache.org/proper/commons-lang/[Apache Commons Lang] and
-then modified to support evaluating LogEvents. In addition the
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/Interpolator.html[`Interpolator`]
-class was borrowed from Apache Commons Configuration to allow the
-StrSubstitutor to evaluate variables 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 xref:manual/lookups.adoc[Lookups]
-for more information.
+See xref:manual/configuration.adoc#property-substitution[how property 
substitution works] and xref:manual/lookups.adoc[the predefined lookups] for 
further information.
diff --git a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc 
b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
index 5d9b94627b..58d8e0dacc 100644
--- a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
@@ -438,7 +438,7 @@ Other logger configurations are optional.
 Every
 link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[`Logger`]
 in your application is assigned to one of these logger configurations (see
-xref:manual/architecture.adoc#loggerconfig[architecture]), which determines 
the events that will be logged and those that won't.
+xref:manual/architecture.adoc#LoggerConfig[architecture]), which determines 
the events that will be logged and those that won't.
 
 Let's start with an example of logger configuration:
 
diff --git a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc 
b/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
index 2c98e3b478..42423e751a 100644
--- a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
@@ -14,6 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
+
 = Levels
 
 Log levels are used to categorize log events by severity and control the 
verbosity of the logs.
@@ -44,6 +45,14 @@ Priority can be used in several contexts to express a 
filtering capability, for
 The entry point to log levels are through 
link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html[`Level`].
 Predefined levels are available for Log4j API integrators through 
link:../javadoc/log4j-api/org/apache/logging/log4j/spi/StandardLevel.html[`StandardLevel`].
 
+[NOTE]
+====
+The `OFF` and `ALL` levels are not intended to be used on calls to the logging 
API.
+Specifying `OFF` in the configuration implies no logging events should match, 
while specifying `ALL` means all events match, including custom events.
+`OFF` can be used on logging API calls in special cases where the event should 
always be logged regardless of the configuration.
+However, it is generally recommended that a xref:manual/markers.adoc[marker] 
with a corresponding global xref:manual/filters.adoc#MarkerFilter[marker 
filter] be used instead.
+====
+
 [#usage]
 == [[StandardLoggerInterface]] Usage
 
@@ -57,39 +66,8 @@ LOGGER.log(Level.INFO, "Hello, {}!", userName); // <2>
 <1> Using `Logger#info()` to log a message at `INFO` level
 <2> Using `Logger#log()` to log a message and specifying the `INFO` level 
explicitly
 
-There are several ways levels can be employed in the Log4j configuration file 
for filtering purposes.
-Filtering on levels for loggers is a pretty common example:
-[source,xml]
-----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-               xmlns="https://logging.apache.org/xml/ns";
-               xsi:schemaLocation="
-                       https://logging.apache.org/xml/ns
-                       https://logging.apache.org/xml/ns/log4j-config-2.xsd";>
-
-  <appenders>
-    <Console name="CONSOLE">
-      <JsonTemplateLayout/>
-    </Console>
-  </appenders>
-
-  <loggers>
-    <logger name="com.mycompany" level="INFO"/><!--1-->
-    <root level="ERROR"><!--2-->
-      <AppenderRef ref="CONSOLE"/>
-    </root>
-  </loggers>
-
-</Configuration>
-----
-<1> Logs of level `INFO` or higher severity (i.e., `WARN`, `ERROR`, `FATAL`) 
are allowed for `com.mycompany` package
-<2> Logs of level `ERROR` or higher severity (i.e., `FATAL`) are allowed for 
the rest
-
-[[top]]
-
 [#DefiningLevelsInCode]
-== Defining custom log levels programmatically
+=== Custom log levels
 
 Users can programmatically define custom levels using 
link:../javadoc/log4j-api/org/apache/logging/log4j/Level.html#forName(java.lang.String,int)[the
 `Level.forName()` method]:
 
@@ -122,45 +100,113 @@ public class PurchaseOrder {
 ----
 <1> Logging with the created custom level
 
+[#config]
+== Configuration
+
+Levels can be used in various ways in a configuration file.
+We will explain some important ones from multiple logging implementations.
+
+[#config-core]
+=== Log4j Core
+
+Log4j Core, the reference implementation of Log4j API, has extensive support 
for levels.
+It allows both <<config-core-filter,basic level-based filtering>> and 
<<DefiningLevelsInConfiguration,custom log levels>>.
+
+[#config-core-filter]
+==== Basic filtering
+
+Filtering on levels for loggers is a pretty common example:
+
+[tabs]
+====
+XML::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/filtering/log4j2.xml[`log4j2.xml`] 
configuring level-filtered loggers
+[source,xml]
+----
+include::example$manual/customloglevels/filtering/log4j2.xml[lines=14..19,indent=0]
+----
+
+JSON::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/filtering/log4j2.json[`log4j2.json`]
 configuring level-filtered loggers
+[source,xml]
+----
+include::example$manual/customloglevels/filtering/log4j2.json[lines=9..22,indent=0]
+----
+
+YAML::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/filtering/log4j2.yaml[`log4j2.yaml`]
 configuring level-filtered loggers
+[source,xml]
+----
+include::example$manual/customloglevels/filtering/log4j2.yaml[lines=24..31,indent=0]
+----
+
+Properties::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/filtering/log4j2.properties[`log4j2.properties`]
 configuring level-filtered loggers
+[source,xml]
+----
+include::example$manual/customloglevels/filtering/log4j2.properties[lines=21..24]
+----
+====
+<1> Logs of level `INFO` or higher severity (i.e., `WARN`, `ERROR`, `FATAL`) 
are allowed for `com.mycompany` package
+<2> Logs of level `ERROR` or higher severity (i.e., `FATAL`) are allowed for 
the rest
+
 [#DefiningLevelsInConfiguration]
-== Defining custom log levels in configuration
+==== Custom log levels
 
-Similar to defining log levels programmatically, a custom level must be 
defined first, before it can be used in a configuration file.
+Log4j Core, the reference implementation of Log4j API, requires a custom level 
to be defined first, before it can be used in a configuration file.
 To facilitate this, the `CustomLevel` configuration element is used to define 
a custom level.
 Internally it calls the same `Level.forName()` method discussed in 
<<DefiningLevelsInCode>>.
 
 The following example shows a configuration that defines the `VERBOSE` custom 
log level and uses it to filter log events sent to the console.
 
+[tabs]
+====
+XML::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/custom/log4j2.xml[`log4j2.xml`] 
configuring custom log levels
+[source,xml]
+----
+include::example$manual/customloglevels/custom/log4j2.xml[lines=17..26,indent=0]
+----
+
+JSON::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/custom/log4j2.json[`log4j2.json`] 
configuring custom log levels
 [source,xml]
 ----
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-               xmlns="https://logging.apache.org/xml/ns";
-               xsi:schemaLocation="
-                       https://logging.apache.org/xml/ns
-                       https://logging.apache.org/xml/ns/log4j-config-2.xsd";>
-
-  <CustomLevels><!--1-->
-    <CustomLevel name="VERBOSE" intLevel="550"/>
-  </CustomLevels>
-
-  <appenders>
-    <Console name="CONSOLE">
-      <PatternLayout/>
-    </Console>
-    <File name="FILE" fileName="logs/app.log">
-      <PatternLayout/>
-    </File>
-  </appenders>
-
-  <loggers>
-    <root level="TRACE">
-      <AppenderRef ref="CONSOLE" level="VERBOSE" /><!--2-->
-      <AppenderRef ref="FILE"/>
-    </root>
-  </loggers>
-
-</Configuration>
+include::example$manual/customloglevels/custom/log4j2.json[lines=13..32,indent=0]
 ----
+
+YAML::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/custom/log4j2.yaml[`log4j2.yaml`] 
configuring custom log levels
+[source,xml]
+----
+include::example$manual/customloglevels/custom/log4j2.yaml[lines=27..37,indent=0]
+----
+
+Properties::
++
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/custom/log4j2.properties[`log4j2.properties`]
 configuring custom log levels
+[source,xml]
+----
+include::example$manual/customloglevels/custom/log4j2.properties[lines=24..30]
+----
+====
 <1> Defining the `VERBOSE` custom log level
 <2> Only events of `VERBOSE` level or higher severity are sent to the console
+
+[#config-logback]
+=== Logback
+
+{logback-url}[Logback] can be configured as follows to define level-filtered 
loggers:
+
+.Snippet from an example 
{antora-examples-url}/manual/customloglevels/filtering/logback.xml[`logback.xml`]
 configuring level-filtered loggers
+[source,xml]
+----
+include::example$manual/customloglevels/filtering/logback.xml[lines=29..32,indent=0]
+----
diff --git a/src/site/antora/modules/ROOT/pages/manual/extending.adoc 
b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
index 679aabb23b..463269e16f 100644
--- a/src/site/antora/modules/ROOT/pages/manual/extending.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
@@ -91,7 +91,7 @@ Yet when this happens, you can use 
xref:manual/systemproperties.adoc#log4j2.prov
 [#LoggerContextFactory]
 === `LoggerContextFactory`
 
-link:../javadoc/log4j-api/org/apache/logging/log4j/spi/LoggerContextFactory.html[`LoggerContextFactory`]
 is the factory class used by Log4j API implementations to create 
xref:manual/architecture.adoc#logger-context[`LoggerContext`]s.
+link:../javadoc/log4j-api/org/apache/logging/log4j/spi/LoggerContextFactory.html[`LoggerContextFactory`]
 is the factory class used by Log4j API implementations to create 
xref:manual/architecture.adoc#LoggerContext[`LoggerContext`]s.
 If you are using Log4j Core, you can provide a custom implementation using 
xref:manual/systemproperties.adoc#log4j2.loggerContextFactory[the 
`log4j2.loggerContextFactory` property].
 Another way to provide a custom `LoggerContextFactory` is to 
<<Provider,provide a custom `Provider`>>.
 But this is generally discouraged, since it requires a more complicated setup 
and is intended mostly to be used by Log4j API implementations.
@@ -105,7 +105,7 @@ It can be configured using 
xref:manual/systemproperties.adoc#log4j2.contextSelec
 [#ConfigurationFactory]
 === `ConfigurationFactory`
 
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`]
 is the factory class used by Log4j Core to create 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]
 instances given a 
xref:manual/architecture.adoc#logger-context[`LoggerContext`] and a 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationSource.html[`ConfigurationSource`].
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`]
 is the factory class used by Log4j Core to create 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]
 instances given a xref:manual/architecture.adoc#LoggerContext[`LoggerContext`] 
and a 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationSource.html[`ConfigurationSource`].
 
 You can provide a custom `ConfigurationFactory` in the form of a 
<<Custom_Plugins,plugin>>.
 For example, see 
{project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfigurationFactory.java[`XmlConfigurationFactory.java`]
 and 
{project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/config/xml/XmlConfiguration.java[`XmlConfiguration.java`]
 of Log4j Core.
diff --git a/src/site/antora/modules/ROOT/pages/manual/markers.adoc 
b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
index 0cc8f583f1..a52e36decb 100644
--- a/src/site/antora/modules/ROOT/pages/manual/markers.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
@@ -100,9 +100,7 @@ complex hierarchies of markers where possible.
 == Configuring filtering
 
 Developers can use markers to filter the log statements delivered to log files.
-Marker processing is supported at least by
-https://logback.qos.ch/manual/filters.html[Logback]
-and the Log4j Core logging backends.
+Marker processing is supported at least by 
{logback-url}/manual/filters.html[Logback] and the Log4j Core logging 
implementations.
 We will provide a sample configuration for both these backends.
 
 [#log4j-core]
@@ -154,7 +152,7 @@ 
include::example$manual/markers/log4j2.properties[lines=17..-1]
 
 Logback differentiates two kinds of filters: ``TurboFilter``s, which are 
applied before a log event is created, and
 ``Filter``s, which are applied only when a log event reaches an appender.
-See https://logback.qos.ch/manual/filters.html[Logback filters] for more 
information.
+See {logback-url}/manual/filters.html[Logback filters] for more information.
 
 You can use a combination of `MarkerFilter`, `EvaluatorFilter` and 
`OnMarkerEvaluator` to redirect all messages marked with `SQL` to a specific 
appender, regardless of their level.
 In order to do that, you can use a configuration as below:

Reply via email to