vpelikh commented on code in PR #4230:
URL: https://github.com/apache/logging-log4j2/pull/4230#discussion_r4148081571
##########
src/site/antora/modules/ROOT/pages/manual/architecture.adoc:
##########
@@ -16,468 +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.
+* <<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 and an <<AbstractManager>> to handle the lifecycle of the
target resource.
+* <<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 `AbstractManager`
in order – this is depicted using green arrows in
xref:architecture-diagram[xrefstyle=short].
+
+Following sections examine this interplay in detail.
+
+[#LoggerContext]
+== `LoggerContext`
+
+The
{log4j2-url}/javadoc/log4j-api/org/apache/logging/log4j/spi/LoggerContext.html[`LoggerContext`]
acts as the anchor point for the logging system.
+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]
+== `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
+....
+
+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[].
+
+[#reconfiguration]
+=== Reconfiguration reliability
+
+The main motivation for the existing architecture is the reliability to
configuration changes.
+When a reconfiguration event occurs, two `Configuration` instances are active
at the same time.
+Threads that already started processing a log event will either:
+
+* continue logging to the old configuration, if execution already reached the
`LoggerConfig` class,
+* or switch to the new configuration.
+
+The service that manages the reconfiguration process is called
link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ReliabilityStrategy.html[`ReliabilityStrategy`]
and it decides:
+
+* when should ``Logger``s switch to the new configuration,
+* when should the old configuration be stopped.
+
+.Overview of the reconfiguration process
+[plantuml]
+....
+@startuml
+left to right direction
+
+package LoggerContext {
+ object Logger
+
+ package "New Configuration" as c2 {
+ object "LoggerConfig" as lc2
+ object "AppenderControl" as ac2
+ object "Appender" as app2
+ }
+
+ package "Old Configuration" as c1 {
+ object "LoggerConfig" as lc1
+ object "AppenderControl" as ac1
+ object "Appender" as app1
+ }
+}
+
+object AbstractManager
+
+Logger ..> lc1
+lc1 --> ac1
+ac1 --> app1
+app1 --> AbstractManager
+
+Logger --> lc2
+lc2 --> ac2
+ac2 --> app2
+app2 --> AbstractManager
+@enduml
+....
+
+[#Logger]
Review Comment:
Fixed in
[0722640](https://github.com/apache/logging-log4j2/pull/4230/commits/0722640deabef8b6c1c5d1bbcc96ba385da84ff9).
--
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]