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

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


The following commit(s) were added to refs/heads/doc/2.x/extending by this push:
     new 4c7414c121 Add information about reconfiguration
4c7414c121 is described below

commit 4c7414c1212b2f70e20645aea5b444947ea98667
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Wed Jun 26 14:22:28 2024 +0200

    Add information about reconfiguration
---
 .../modules/ROOT/pages/manual/architecture.adoc    | 256 +++++++++++++--------
 1 file changed, 162 insertions(+), 94 deletions(-)

diff --git a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc 
b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
index 91213fec00..3c9b032d25 100644
--- a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
@@ -36,127 +36,112 @@ 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
-}
+package "Configuration" as c {
 
-note left of Configuration
-  Encapsulates components compiled
-  from a user-provided configuration
-  file (e.g., `log4j2.xml`)
-end note
+    class Configuration {
+      Appender[] appenders
+      Filter[] filters
+      LoggerConfig[] loggerConfigs
+      LoggerConfig getLoggerConfig(String name)
+      StrSubstitutor substitutor
+    }
 
-Configuration --> "0..*" Filter
+    note left of Configuration
+      Encapsulates components compiled
+      from a user-provided configuration
+      file (e.g., `log4j2.xml`)
+    end note
 
-Configuration --> "0..*" Appender
+    Configuration --> Filter
 
-Configuration --> "0..*" LoggerConfig
+    Configuration --> "0..*" Appender
 
-Configuration --> StrSubstitutor
+    Configuration --> "0..*" LoggerConfig
 
-class Appender {
-  Layout layout
-  void append(LogEvent)
-}
+    Configuration --> StrSubstitutor
 
-Appender -[#green,thickness=6]-> Layout
+    class Appender {
+      AbstractManager manager
+      Layout layout
+      Filter filter
+      void append(LogEvent)
+    }
 
-class Layout {
-  byte[] encode(LogEvent)
-}
+    Appender --> Layout
 
-class Filter {
-  Result filter(LogEvent)
-}
+    Appender --> Filter
 
-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 Layout {
+      byte[] encode(LogEvent)
+    }
 
-class LoggerConfig {
-  AppenderRef[] appenderRefs
-  AppenderControl[] appenderControls
-  Level level
-  Filter filter
-  void log(LogEvent)
-}
+    class Filter {
+      Result filter(LogEvent)
+    }
 
-LoggerConfig --> "0..*" AppenderRef
+    note right of Filter
+      Note that a `Filter` can
+      be provided at 4 levels:
+      1. `Configuration`
+      2. `LoggerConfig`
+      3. `AppenderControl`
+      4. `Appender`
+    end note
 
-LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
+    class LoggerConfig {
+      AppenderControl[] appenderControls
+      Level level
+      Filter filter
+      void log(LogEvent)
+    }
 
-LoggerConfig --> Filter
+    LoggerConfig -[#green,thickness=6]-> "0..*" AppenderControl
 
-class AppenderRef {
-  String appenderName
-  Level level
-  Filter filter
-}
+    LoggerConfig --> Filter
 
-note right of AppenderRef
-  Denotes a user-provided
-  appender configuration
-  for a `Logger`,
-  e.g., `<AppenderRef`
-  element in a `log4j2.xml`.
+    class AppenderControl {
+      Appender appender
+      Filter filter
+      void append(LogEvent)
+    }
 
-  It is used to populate
-  `AppenderControl`s.
-end note
+    note right of AppenderControl
+      Decorates an `Appender`
+      with a `Filter`
+    end note
 
-AppenderRef --> Filter
+    AppenderControl -[#green,thickness=6]-> Appender
 
-class AppenderControl {
-  Appender appender
-  Filter filter
-  void append(LogEvent)
-}
+    AppenderControl --> Filter
 
-note right of AppenderControl
-  Decorates an `Appender`
-  with a `Filter`
-end note
-
-AppenderControl -[#green,thickness=6]-> Appender
+    class StrSubstitutor {
+      Interpolator interpolator
+      String replace(String input)
+    }
 
-AppenderControl --> Filter
+    note right of StrSubstitutor
+      Responsible for
+      property substitution
+      (e.g., `${env:USER}`)
+    end note
 
-class StrSubstitutor {
-  Interpolator interpolator
-  String replace(String input)
-}
+    StrSubstitutor --> Interpolator
 
-note right of StrSubstitutor
-  Responsible for
-  property substitution
-  (e.g., `${env:USER}`)
-end note
+    class Interpolator {
+      StrLookup[] lookups
+      String lookup(String input)
+    }
 
-StrSubstitutor --> Interpolator
+    Interpolator --> "0..*" StrLookup
 
-class Interpolator {
-  StrLookup[] lookups
-  String lookup(String input)
+    class StrLookup {
+      String lookup(String input)
+    }
 }
 
-Interpolator --> "0..*" StrLookup
-
-class StrLookup {
-  String lookup(String input)
-}
+LoggerContext --> Configuration
 
 class Logger {
   void log(Level level, Message message)
@@ -169,6 +154,11 @@ end note
 
 Logger -[#green,thickness=6]-> LoggerConfig : delegates `log()`
 
+class AbstractManager {
+}
+
+Appender -[#green,thickness=6]-> AbstractManager
+
 @enduml
 ....
 
@@ -177,13 +167,70 @@ 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.
+* <<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
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/AbstractManager.html[`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 `Layout` in order 
– this is depicted using green arrows in 
xref:architecture-diagram[xrefstyle=short].
+* 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.
 
+[#reconfiguration]
+== Reconfiguration reliability
+
+The main motivation for such an architecture is 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
+....
+
 [#LoggerContext]
 == `LoggerContext`
 
@@ -730,6 +777,27 @@ In xref:#appender-additivity-diagram[xrefstyle=short], the 
effective appenders f
 |===
 ====
 
+[#AbstractManager]
+=== `AbstractManager`
+
+To multiplex the access to external resources (files, network connections, 
etc.), most appenders are split into an
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/AbstractManager.html[`AbstractManager`]
+that handles the low-level access to the external resource and an `Appender` 
that transforms log events into a format that the manager can handle.
+
+Managers that share the same resource are shared between appenders regardless 
of the `Configuration` or `LoggerContext` of the appenders.
+For example
+xref:manual/appenders.adoc#FileAppender[`FileAppender`]s
+with the same `fileName` attribute all share the same
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/FileManager.html[`FileManager`].
+
+[IMPORTANT]
+====
+Due to the manager-sharing feature of many Log4j appenders, it is not possible 
to configure multiple appenders for the same resource that only differ in the 
way the underlying resource is configured.
+
+For example, it is not possible to have two file appenders (even in different 
logger contexts) that use the same file, but a different value of the `append` 
option.
+Since during a <<reconfiguration,reconfiguration event>> multiple instances of 
the same appender exists, it is also not possible to toggle the value of the 
`append` option through reconfiguration.
+====
+
 [#Layout]
 == `Layout`
 

Reply via email to