jvz commented on code in PR #2716:
URL: https://github.com/apache/logging-log4j2/pull/2716#discussion_r1668960552


##########
src/site/antora/modules/ROOT/pages/manual/architecture.adoc:
##########
@@ -16,467 +16,848 @@
 ////
 = 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
-{log4j2-url}/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].
-
-=== LoggerContext
-
-The
-link:../javadoc/log4j-core/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
-xref:manual/logsep.adoc[Log Separation] section.
-
-=== 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
-
-As stated previously, Loggers are created by calling
-{log4j2-url}/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
-{log4j2-url}/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
-{log4j2-url}/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 
{log4j2-url}/manual/customloglevels.adoc[custom log
-levels]. Another mechanism for getting more granularity is to use
-{log4j2-url}/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
+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 --> "0..*" Logger
+
+package "Configuration" as c {
+
+    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 --> Filter
+
+    Configuration --> "0..*" Appender

Review Comment:
   The PlantUML [docs](https://plantuml.com/class-diagram) have some other 
relation types you can use here like `o--` for aggregation and `*--` for 
composition, though I've used the aggregation relation before to denote when 
one class has an array or collection of another class. What you've done here, 
though, is probably easier to understand for people who don't write UML 
diagrams :)



##########
src/site/antora/modules/ROOT/pages/manual/architecture.adoc:
##########
@@ -16,467 +16,848 @@
 ////
 = 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
-{log4j2-url}/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].
-
-=== LoggerContext
-
-The
-link:../javadoc/log4j-core/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
-xref:manual/logsep.adoc[Log Separation] section.
-
-=== 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
-
-As stated previously, Loggers are created by calling
-{log4j2-url}/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
-{log4j2-url}/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
-{log4j2-url}/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 
{log4j2-url}/manual/customloglevels.adoc[custom log
-levels]. Another mechanism for getting more granularity is to use
-{log4j2-url}/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
+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 --> "0..*" Logger
+
+package "Configuration" as c {
+
+    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 --> Filter
+
+    Configuration --> "0..*" Appender
+
+    Configuration --> "0..*" LoggerConfig
+
+    Configuration --> StrSubstitutor
+
+    class Appender {
+      AbstractManager manager
+      Layout layout
+      Filter filter
+      void append(LogEvent)
+    }
+
+    Appender --> Layout
+
+    Appender --> Filter
+
+    class Layout {
+      byte[] encode(LogEvent)

Review Comment:
   Possibly worth noting the parent interface, `Encoder<LogEvent>`, which adds 
a `void encode(LogEvent, ByteBufferDestination)` method, but that also requires 
adding `ByteBufferDestination` to the diagram, and that might be getting too 
deep into technical minutiae. What do you think?



##########
src/site/antora/modules/ROOT/pages/manual/layouts.adoc:
##########
@@ -557,6 +557,11 @@ include::partial$manual/plugin-preliminaries.adoc[]
 
 Layouts are xref:manual/plugins.adoc[plugins] implementing 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/Layout.html[the 
`Layout` interface].
 If your layout is a `String`-based one, we recommend you to extend your plugin 
class from 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/layout/AbstractStringLayout.html[`AbstractStringLayout`],
 which contains convenience for some of the boilerplate code shared by 
`String`-based layouts.
+While annotating your layout with `@Plugin`, you need to make sure that
+
+* It has a unique `name` attribute across all available `Layout` plugins

Review Comment:
   Technically, it'd have to be a unique `name` attribute for all `Core` 
category/namespace plugins as this name determines the XML element name it 
aliases to. Had we used different categories for different plugin types, then 
that would likely correspond to XML namespaces which would make the config file 
more complicated to write.



##########
src/site/antora/modules/ROOT/pages/manual/plugins.adoc:
##########
@@ -14,244 +14,265 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
+
 = Plugins
 
-Log4j 1.x allowed for extension by requiring class attributes on most of
-the configuration declarations. In the case of some elements, notably
-the PatternLayout, the only way to add new pattern converters was to
-extend the PatternLayout class and add them via code. One goal of Log4j
-2 is to make extending it extremely easy through the use of plugins.
-
-In Log4j 3.x, a plugin is declared by adding a `@Plugin` and `@Namespace` 
annotation to the class declaration.
-During initialization the
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]
-will invoke the `PluginRegistry`
-to load the built-in Log4j plugins as well as any custom plugins. The
-`Injector` locates plugins by looking in the following places:
-
-1.  Plugin collection classes on the classpath that are loaded by 
java.util.ServiceLoader.
-These classes are generated automatically during the build (more details 
below).
-2.  (OSGi only) Serialized plugin listing files in each active OSGi
-bundle. A `BundleListener` is added on activation to continue checking
-new bundles after `log4j-plugins` has started. Bundles must register their 
plugin collection
-class as an OSGi service.
-3. Serialized plugin listing files on the classpath. These files were 
generated by
-the plugin annotation processor in Log4j 2 2.x. These are processed to allow
-compatibility.
-
-When multiple plugins use the same case-insensitive `name` within the same 
plugin category, then which one is selected is determined first by the presence 
of `@PluginOrder` annotations and then by the previously described plugin 
loading order.
-For example, to override the `File` plugin which is provided by the built-in 
`FileAppender` class, you would need to place your plugin in a JAR file in the 
CLASSPATH ahead of`log4j-core.jar`.
-This is not recommended; plugin name collisions will cause a warning to be 
emitted.
-Note that in an OSGi environment, the order that bundles are scanned for 
plugins generally follows the same order that bundles were installed into the 
framework.
-See 
https://www.osgi.org/javadoc/r5/core/org/osgi/framework/BundleContext.html#getBundles()[`getBundles()`]
 and 
https://www.osgi.org/javadoc/r5/core/org/osgi/framework/SynchronousBundleListener.html[`SynchronousBundleListener`].
-In short, name collisions are even more unpredictable in an OSGi environment 
without additional `@PluginOrder` usage.
-
-Plugin collection classes are generated by an annotation processor contained
-in the log4j-plugins artifact which will automatically scan your code for
-Log4j 2 plugins and generate a Java source file that references all the
-located plugins. It will also generate a
-META-INF/services/org.apache.logging.log4j.plugins.model.PluginService
-file in compliance with java.util.ServiceLoader.
-There is nothing extra that needs to be done to enable this;
-the Java compiler will automatically pick up the annotation processor on
-the class path unless you explicitly disable it.
-
-If annotation processing is disabled plugins may still be registered by either
-[loweralpha]
-.. manually providing a class that extends 
`org.apache.logging.log4j.plugins.model.PluginService`
-and identifies all the plugins and also declaring a
-`META-INF/services/org.apache.logging.log4j.plugins.model.PluginService` file
-that provides the fully qualified name of the implemented class or
-.. adding another compiler pass to the build process that
-only handles annotation processing using the Log4j 2 annotation
-processor class,
-`org.apache.logging.log4j.plugin.processor.PluginProcessor`.
-To do this using Apache Maven, add the following execution to your
-_maven-compiler-plugin_ (version 2.2 or higher) build plugin:
-
-[source,xml]
+Log4j plugin system is the de facto extension mechanism embraced by various 
Log4j Core components.
+Plugins make it possible for extensible components to _receive_ feature 
implementations without any explicit links in between.
+It is analogous to a 
https://en.wikipedia.org/wiki/Dependency_injection[dependency injection] 
framework, but curated for Log4j-specific needs.
+
+[NOTE]
+====
+Log4j plugin system is implemented by Log4j Core, the logging implementation.
+It is deliberately not a part of the Log4j API to keep the logging API 
footprint small.
+====
+
+[TIP]
+====
+Did you know about *xref:plugin-reference.adoc[], the documentation extracted 
from the source code* of all predefined Log4j plugins?
+Like Javadoc, but specialized for plugins!
+====
+
+In this section we will give an overview of the Log4j plugin system by 
answering certain questions:
+
+. <<#declare-plugin,How can you declare a plugin?>>
+. <<#core,How can you declare a plugin that needs to be represented in a Log4j 
configuration file?>>
+. <<#plugin-registry,How can you register your plugin to Log4j?>>
+. <<#plugin-discovery,How does Log4j discover plugins?>>
+. <<#plugin-load,How can you load other plugins in a plugin?>>
+
+[#declare-plugin]
+== Declaring plugins
+
+A class can be declared as a plugin by adding a 
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/Plugin.html[`@Plugin`]
 annotation, which is essentially composed of following attributes:
+
+`name`::
+Name of the plugin.
+It is recommended to be distinct among plugins sharing the same `category`.

Review Comment:
   It's pretty important; you can disambiguate which plugin uses the name based 
on plugin order I think, but they otherwise need to be unique in a category/



##########
src/site/antora/modules/ROOT/pages/manual/architecture.adoc:
##########
@@ -16,467 +16,848 @@
 ////
 = 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
-{log4j2-url}/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].
-
-=== LoggerContext
-
-The
-link:../javadoc/log4j-core/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
-xref:manual/logsep.adoc[Log Separation] section.
-
-=== 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
-
-As stated previously, Loggers are created by calling
-{log4j2-url}/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
-{log4j2-url}/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
-{log4j2-url}/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 
{log4j2-url}/manual/customloglevels.adoc[custom log
-levels]. Another mechanism for getting more granularity is to use
-{log4j2-url}/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
+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 --> "0..*" Logger
+
+package "Configuration" as c {
+
+    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 --> Filter
+
+    Configuration --> "0..*" Appender
+
+    Configuration --> "0..*" LoggerConfig
+
+    Configuration --> StrSubstitutor
+
+    class Appender {
+      AbstractManager manager
+      Layout layout
+      Filter filter
+      void append(LogEvent)
+    }
+
+    Appender --> Layout
+
+    Appender --> Filter
+
+    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. `AppenderControl`
+      4. `Appender`
+    end note
+
+    class LoggerConfig {
+      AppenderControl[] appenderControls
+      Level level
+      Filter filter
+      void log(LogEvent)
+    }
+
+    LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
+
+    LoggerConfig --> 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)
+    }
+}
+
+LoggerContext --> Configuration
+
+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()`
+
+class AbstractManager {
+}
+
+Appender -[#green,thickness=6]-> AbstractManager
+
+@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.

Review Comment:
   Could be worth mentioning that `Logger` and `LoggerConfig` work via a bridge 
pattern where `Logger` provides the API and `LoggerConfig` provides the 
implementation. This is one key architectural constraint that allows for 
reconfiguration without dropping any log events being processed at the time of 
reconfiguration. It's also one of the reasons why many methods of manual 
configuration of appenders and such is so hard to do properly and why we offer 
various utility methods and configuration DSLs to sort of hide away the 
lifecycle handling, concurrency, etc.



##########
src/site/antora/modules/ROOT/pages/manual/architecture.adoc:
##########
@@ -16,467 +16,848 @@
 ////
 = 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
-{log4j2-url}/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].
-
-=== LoggerContext
-
-The
-link:../javadoc/log4j-core/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
-xref:manual/logsep.adoc[Log Separation] section.
-
-=== 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
-
-As stated previously, Loggers are created by calling
-{log4j2-url}/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
-{log4j2-url}/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
-{log4j2-url}/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 
{log4j2-url}/manual/customloglevels.adoc[custom log
-levels]. Another mechanism for getting more granularity is to use
-{log4j2-url}/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
+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

Review Comment:
   This UML diagram is pretty awesome!



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to