You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by vy...@apache.org on 2024/07/03 08:06:57 UTC

(logging-log4j2) branch 2.x updated: Revamp the `Extending`, `Plugins`, `Architecture`, and `Programmatic configuration` pages (#2696)

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

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


The following commit(s) were added to refs/heads/2.x by this push:
     new 466ac59759 Revamp the `Extending`, `Plugins`, `Architecture`, and `Programmatic configuration` pages (#2696)
466ac59759 is described below

commit 466ac597590278a087e70d176679a68c4f096a2e
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Wed Jul 3 10:06:52 2024 +0200

    Revamp the `Extending`, `Plugins`, `Architecture`, and `Programmatic configuration` pages (#2696)
    
    Co-authored-by: Piotr P. Karwasz <pi...@karwasz.org>
---
 .../customconfig/ConfigurationBuilder/log4j2.json  |   18 +
 .../ConfigurationBuilder/log4j2.properties         |   22 +
 .../customconfig/ConfigurationBuilder/log4j2.xml   |   36 +
 .../customconfig/ConfigurationBuilder/log4j2.yaml  |   28 +
 .../manual/customconfig/ExampleConfiguration.java  |   47 +
 .../customconfig/ExampleConfigurationFactory.java  |   46 +
 .../ROOT/examples/manual/customconfig/Usage.java   |   90 ++
 .../antora/modules/ROOT/images/Log4jClasses.jpg    |  Bin 31443 -> 0 bytes
 src/site/antora/modules/ROOT/pages/manual/api.adoc |    5 +
 .../modules/ROOT/pages/manual/appenders.adoc       |  165 ++-
 .../modules/ROOT/pages/manual/architecture.adoc    | 1233 +++++++++++++-------
 .../modules/ROOT/pages/manual/config-intro.adoc    |   15 +-
 .../modules/ROOT/pages/manual/configuration.adoc   |  200 ++--
 .../modules/ROOT/pages/manual/customconfig.adoc    |  498 +++-----
 .../modules/ROOT/pages/manual/customloglevels.adoc |    2 +-
 .../modules/ROOT/pages/manual/extending.adoc       |  592 ++--------
 .../antora/modules/ROOT/pages/manual/filters.adoc  |   65 +-
 .../modules/ROOT/pages/manual/garbagefree.adoc     |    2 +-
 .../antora/modules/ROOT/pages/manual/layouts.adoc  |    5 +
 .../antora/modules/ROOT/pages/manual/lookups.adoc  |   83 +-
 .../antora/modules/ROOT/pages/manual/markers.adoc  |    6 +-
 .../modules/ROOT/pages/manual/pattern-layout.adoc  |   60 +-
 .../antora/modules/ROOT/pages/manual/plugins.adoc  |  271 ++++-
 .../partials/configuration-file-format-deps.adoc   |   18 +-
 .../partials/manual/composite-configuration.adoc   |   50 +
 .../ROOT/partials/manual/plugin-preliminaries.adoc |    2 +-
 src/site/resources/.htaccess                       |   41 -
 27 files changed, 2049 insertions(+), 1551 deletions(-)

diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.json b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.json
new file mode 100644
index 0000000000..5ad06b4cd6
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.json
@@ -0,0 +1,18 @@
+{
+  "Configuration": {
+    "Appenders": {
+      "Console": {
+        "name": "CONSOLE",
+        "JsonTemplateLayout": {}
+      }
+    },
+    "Loggers": {
+      "Root": {
+        "level": "WARN",
+        "AppenderRef": {
+          "ref": "CONSOLE"
+        }
+      }
+    }
+  }
+}
diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.properties b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.properties
new file mode 100644
index 0000000000..bd45ad2d7b
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.properties
@@ -0,0 +1,22 @@
+#
+# 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
+
+rootLogger.level = WARN
+rootLogger.appenderRef.0.ref = CONSOLE
diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.xml b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.xml
new file mode 100644
index 0000000000..3acc82eb21
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.xml
@@ -0,0 +1,36 @@
+<?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.
+  -->
+<Configuration xmlns="https://logging.apache.org/xml/ns"
+               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+               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>
+    <Root level="WARN">
+      <AppenderRef ref="CONSOLE"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.yaml b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.yaml
new file mode 100644
index 0000000000..a46826acd4
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/ConfigurationBuilder/log4j2.yaml
@@ -0,0 +1,28 @@
+#
+# 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:
+    Root:
+      level: "WARN"
+      AppenderRef:
+        ref: "CONSOLE"
diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/ExampleConfiguration.java b/src/site/antora/modules/ROOT/examples/manual/customconfig/ExampleConfiguration.java
new file mode 100644
index 0000000000..5d8a00b424
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/ExampleConfiguration.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package com.example;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.AppenderRef;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+
+public class ExampleConfiguration extends XmlConfiguration {
+
+    public ExampleConfiguration(LoggerContext loggerContext, ConfigurationSource configSource) {
+        super(loggerContext, configSource);
+    }
+
+    @Override
+    protected void doConfigure() {
+        Appender appender = createAppender("ExampleAppender");
+        appender.start();
+        addAppender(appender);
+        LoggerConfig loggerConfig = LoggerConfig.newBuilder()
+                .withConfig(this)
+                .withAdditivity(false)
+                .withLevel(Level.INFO)
+                .withLoggerName("com.example")
+                .withRefs(new AppenderRef[] {AppenderRef.createAppenderRef("ExampleAppender", null, null)})
+                .build();
+        loggerConfig.addAppender(appender, null, null);
+        addLogger("com.example", loggerConfig);
+    }
+}
diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/ExampleConfigurationFactory.java b/src/site/antora/modules/ROOT/examples/manual/customconfig/ExampleConfigurationFactory.java
new file mode 100644
index 0000000000..25a625c1b1
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/ExampleConfigurationFactory.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package com.example;
+
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.Order;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+
+// tag::class[]
+@Order(100)
+@Plugin(name = "ExampleConfigurationFactory", category = ConfigurationFactory.CATEGORY)
+public class ExampleConfigurationFactory extends ConfigurationFactory {
+
+    @Override
+    public Configuration getConfiguration(LoggerContext loggerContext, ConfigurationSource source) { // <1>
+        // Return a `Configuration`...
+    }
+
+    @Override
+    public Configuration getConfiguration(LoggerContext loggerContext, String name, URI configLocation) {
+        // Return a `Configuration`...
+    }
+
+    @Override
+    public String[] getSupportedTypes() {
+        return new String[] {"*"};
+    }
+}
+// end::class[]
diff --git a/src/site/antora/modules/ROOT/examples/manual/customconfig/Usage.java b/src/site/antora/modules/ROOT/examples/manual/customconfig/Usage.java
new file mode 100644
index 0000000000..bdd5dd6772
--- /dev/null
+++ b/src/site/antora/modules/ROOT/examples/manual/customconfig/Usage.java
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+package com.example;
+
+import java.net.URI;
+import java.util.Arrays;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilder;
+import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
+import org.apache.logging.log4j.core.config.builder.impl.BuiltConfiguration;
+import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
+
+final class Usage {
+
+    private static Configuration createConfiguration() {
+        // tag::createConfiguration[]
+        ConfigurationBuilder<BuiltConfiguration> configBuilder =
+                ConfigurationBuilderFactory.newConfigurationBuilder(); // <1>
+        Configuration configuration = configBuilder
+                .add(
+                        configBuilder // <2>
+                                .newAppender("CONSOLE", "List")
+                                .add(configBuilder.newLayout("JsonTemplateLayout")))
+                .add(
+                        configBuilder // <3>
+                                .newRootLogger(Level.WARN)
+                                .add(configBuilder.newAppenderRef("CONSOLE")))
+                .build(false); // <4>
+        // end::createConfiguration[]
+    }
+
+    private static void useConfiguration() {
+        // tag::useConfiguration[]
+        Configuration configuration = createConfiguration();
+        try (LoggerContext loggerContext = Configurator.initialize(configuration)) {
+            // Use `LoggerContext`...
+        }
+        // end::useConfiguration[]
+    }
+
+    private static void reconfigureActiveLoggerContext() {
+        // tag::reconfigureActiveLoggerContext[]
+        Configuration configuration = createConfiguration();
+        Configurator.reconfigure(configuration);
+        // end::reconfigureActiveLoggerContext[]
+    }
+
+    private static Configuration loadConfigurationFile() {
+        // tag::loadConfigurationFile[]
+        ConfigurationFactory.getInstance()
+                .getConfiguration(
+                        null, // <1>
+                        null, // <2>
+                        URI.create("uri://to/my/log4j2.xml")); // <3>
+        // end::loadConfigurationFile[]
+    }
+
+    private static Configuration combineConfigurations() {
+        // tag::combineConfigurations[]
+        ConfigurationFactory configFactory = ConfigurationFactory.getInstance();
+        AbstractConfiguration commonConfig = (AbstractConfiguration) // <2>
+                configFactory.getConfiguration(null, null, URI.create("classpath:log4j2-common.xml")); // <1>
+        AbstractConfiguration appConfig = (AbstractConfiguration) // <2>
+                configFactory.getConfiguration(null, null, URI.create("classpath:log4j2-app.xml")); // <1>
+        AbstractConfiguration runtimeConfig = ConfigurationBuilderFactory.newConfigurationBuilder()
+                // ...
+                .build(false); // <3>
+        return new CompositeConfiguration(Arrays.asList(commonConfig, appConfig, runtimeConfig)); // <4>
+        // end::combineConfigurations[]
+    }
+}
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/api.adoc b/src/site/antora/modules/ROOT/pages/manual/api.adoc
index 174c5abcfc..dc8d18df73 100644
--- a/src/site/antora/modules/ROOT/pages/manual/api.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/api.adoc
@@ -85,6 +85,11 @@ include::partial$manual/api-best-practice-use-supplier.adoc[]
 link:../javadoc/log4j-api/org/apache/logging/log4j/Logger.html[`Logger`]s are the primary entry point for logging.
 In this section we will introduce you to further details about ``Logger``s.
 
+[TIP]
+====
+Refer to xref:manual/architecture.adoc[] to see where ``Logger``s stand in the big picture.
+====
+
 [#logger-names]
 === Logger names
 
diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index 484b4ff38e..23ef540f73 100644
--- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
@@ -14,8 +14,8 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
+
 = Appenders
-Ralph Goers; Gary Gregory; Nick Williams; Matt Sicker
 
 Appenders are responsible for delivering LogEvents to their destination.
 Every Appender must implement the
@@ -69,8 +69,14 @@ This setting only guarantees that a byte representation of the log event is pass
 It does not ensure that the operating system writes the event to the underlying storage.
 ====
 
+[#collection]
+== Collection
+
+Log4j bundles several predefined appenders to assist in several common deployment use cases.
+Following sections explain all these in detail.
+
 [id=AsyncAppender]
-== [[asyncappender]] AsyncAppender
+=== [[asyncappender]] AsyncAppender
 
 The AsyncAppender accepts references to other Appenders and causes LogEvents to be written to them on a separate Thread.
 Note that exceptions while writing to those Appenders will be hidden from the application.
@@ -232,7 +238,7 @@ maximum capacity.
 |=======================================================================
 
 [#CassandraAppender]
-== CassandraAppender
+=== CassandraAppender
 
 The CassandraAppender writes its output to an https://cassandra.apache.org/[Apache Cassandra]
 database.
@@ -371,7 +377,7 @@ CREATE TABLE logs (
 ----
 
 [id=consoleappender]
-== [[ConsoleAppender]] ConsoleAppender
+=== [[ConsoleAppender]] ConsoleAppender
 
 As one might expect, the ConsoleAppender writes its output to either
 `System.out` or `System.err` with `System.out` being the default target.
@@ -434,7 +440,7 @@ A typical Console configuration might look like:
 ----
 
 [#FailoverAppender]
-== FailoverAppender
+=== FailoverAppender
 
 The FailoverAppender wraps a set of appenders.
 If the primary Appender fails the secondary appenders will be tried in order until one succeeds or there are no more secondaries to try.
@@ -497,7 +503,7 @@ A Failover configuration might look like:
 ----
 
 [id=fileappender]
-== [[FileAppender]] FileAppender
+=== [[FileAppender]] FileAppender
 
 The FileAppender is an OutputStreamAppender that writes to the File defined in the `fileName` parameter.
 The FileAppender uses a FileManager (which extends OutputStreamManager) to perform the file I/O.
@@ -625,7 +631,7 @@ Here is a sample File configuration:
 ----
 
 [#FlumeAppender]
-== FlumeAppender
+=== FlumeAppender
 
 _This is an optional component supplied in a separate jar._
 
@@ -857,7 +863,7 @@ A sample FlumeAppender configuration that is configured with a primary and a sec
 ----
 
 [#JDBCAppender]
-== JDBCAppender
+=== JDBCAppender
 
 As of Log4j 2.11.0, JDBC support has moved from the existing module
 `log4j-core` to the new module `log4j-jdbc`.
@@ -1252,7 +1258,7 @@ table based on a Log4j `MapMessage` instead of values from `LogEvent`.
 ----
 
 [#jms-appender]
-== [[JMSAppender]]JMS Appender
+=== [[JMSAppender]]JMS Appender
 
 The JMS Appender sends the formatted log event to a JMS Destination.
 
@@ -1385,7 +1391,7 @@ To map your Log4j `MapMessage` to JMS `javax.jms.MapMessage`, set the layout of
 ----
 
 [[JPAAppender]]
-== JPAAppender
+=== JPAAppender
 
 As of Log4j 2.11.0, JPA support has moved from the existing module `log4j-core` to the new module `log4j-jpa`.
 
@@ -1563,7 +1569,7 @@ public class JpaLogEntity extends AbstractLogEventWrapperEntity {
 ----
 
 [#HttpAppender]
-== HttpAppender
+=== HttpAppender
 
 The HttpAppender sends log events over HTTP.
 A Layout must be provided to format the LogEvent.
@@ -1637,7 +1643,7 @@ Here is a sample HttpAppender configuration snippet:
 ----
 
 [[KafkaAppender]]
-== KafkaAppender
+=== KafkaAppender
 
 The KafkaAppender logs events to an https://kafka.apache.org/[Apache Kafka] topic.
 Each log event is sent as a Kafka record.
@@ -1722,7 +1728,7 @@ _Note:_ Make sure to not let `org.apache.kafka` log to a Kafka appender on DEBUG
 ----
 
 [#MemoryMappedFileAppender]
-== MemoryMappedFileAppender
+=== MemoryMappedFileAppender
 
 _New since 2.1. Be aware that this is a new addition, and although it has been tested on several platforms, it does not have as much track record as the other file appenders._
 
@@ -1817,7 +1823,7 @@ Here is a sample MemoryMappedFile configuration:
 ----
 
 [#NoSQLAppender]
-== NoSQLAppender
+=== NoSQLAppender
 
 The NoSQLAppender writes log events to a NoSQL database using an internal lightweight provider interface.
 Provider implementations currently exist for MongoDB, and writing a custom provider is quite simple.
@@ -1908,10 +1914,10 @@ The following example demonstrates how log events are persisted in NoSQL databas
 ----
 
 [#NoSQLAppenderMongoDB]
-=== NoSQL providers for MongoDB
+==== NoSQL providers for MongoDB
 
 [#mongo-installation]
-==== Installation
+===== Installation
 
 Starting with version 2.11.0, Log4j supplies providers for the
 https://www.mongodb.com/[MongoDB]
@@ -1981,7 +1987,7 @@ If you are note sure, which implementation to choose, `log4j-mongodb` is the rec
 ====
 
 [#log4j-mongodb]
-==== NoSQL provider for MongoDB (current)
+===== NoSQL provider for MongoDB (current)
 
 This section details specializations of the
 <<NoSQLAppender>> provider for MongoDB using the current MongoDB driver (version 5).
@@ -2070,7 +2076,7 @@ You can define additional fields to log using KeyValuePair elements, for example
 ----
 
 [#log4j-mongodb4]
-==== [[NoSQLAppenderMongoDB4]] NoSQL provider  for MongoDB 4 (deprecated)
+===== [[NoSQLAppenderMongoDB4]] NoSQL provider  for MongoDB 4 (deprecated)
 
 The `log4j-mongodb4` module is deprecated in favor of <<log4j-mongodb,NoSQL provider for MongoDB>>.
 
@@ -2160,7 +2166,7 @@ You can define additional fields to log using KeyValuePair elements, for example
 ----
 
 [[NoSQLAppenderApacheCouchDB]]
-== NoSQLAppender for Apache CouchDB
+=== NoSQLAppender for Apache CouchDB
 
 This section details specializations of the <<NoSQLAppender>> provider for CouchDB.
 The NoSQLAppender writes log events to a NoSQL database using an internal lightweight provider interface.
@@ -2223,7 +2229,7 @@ Here are a few sample configurations for the NoSQLAppender and CouchDB provider:
 ----
 
 [#OutputStreamAppender]
-== OutputStreamAppender
+=== OutputStreamAppender
 
 The OutputStreamAppender provides the base for many of the other Appenders such as the File and Socket appenders that write the event to an Output Stream.
 It cannot be directly configured.
@@ -2231,7 +2237,7 @@ Support for immediateFlush and buffering is provided by the OutputStreamAppender
 The OutputStreamAppender uses an OutputStreamManager to handle the actual I/O, allowing the stream to be shared by Appenders in multiple configurations.
 
 [#RandomAccessFileAppender]
-== RandomAccessFileAppender
+=== RandomAccessFileAppender
 
 The RandomAccessFileAppender is similar to the standard
 <<FileAppender>> except it is always buffered (this cannot be switched off) and internally it uses a
@@ -2311,7 +2317,7 @@ Here is a sample RandomAccessFile configuration:
 ----
 
 [#RewriteAppender]
-== RewriteAppender
+=== RewriteAppender
 
 The RewriteAppender allows the LogEvent to be manipulated before it is processed by another Appender.
 This can be used to mask sensitive information such as passwords or to inject information into each event.
@@ -2343,13 +2349,13 @@ Appender in a <<FailoverAppender>>.
 |=======================================================================
 
 [#RewritePolicy]
-=== RewritePolicy
+==== RewritePolicy
 
 RewritePolicy is an interface that allows implementations to inspect and possibly modify LogEvents before they are passed to Appender.
 RewritePolicy declares a single method named rewrite that must be implemented.
 The method is passed the LogEvent and can return the same event or create a new one.
 
-==== MapRewritePolicy
+===== MapRewritePolicy
 
 MapRewritePolicy will evaluate LogEvents that contain a MapMessage and will add or update elements of the Map.
 
@@ -2385,7 +2391,7 @@ The following configuration shows a RewriteAppender configured to add a product
 </Configuration>
 ----
 
-==== PropertiesRewritePolicy
+===== PropertiesRewritePolicy
 
 PropertiesRewritePolicy will add properties configured on the policy to the ThreadContext Map being logged.
 The properties will not be added to the actual ThreadContext Map.
@@ -2424,7 +2430,7 @@ The following configuration shows a RewriteAppender configured to add a product
 </Configuration>
 ----
 
-==== LoggerNameLevelRewritePolicy
+===== LoggerNameLevelRewritePolicy
 
 You can use this policy to make loggers in third-party code less chatty by changing event levels.
 The LoggerNameLevelRewritePolicy will rewrite log event levels for a given logger name prefix.
@@ -2467,7 +2473,7 @@ The following configuration shows a RewriteAppender configured to map level INFO
 ----
 
 [id=rollingfileappender]
-== [[RollingFileAppender]] RollingFileAppender
+=== [[RollingFileAppender]] RollingFileAppender
 
 The RollingFileAppender is an OutputStreamAppender that writes to the file named in the fileName parameter and rolls the file over according to the `TriggeringPolicy` and the `RolloverPolicy`.
 The `RollingFileAppender`
@@ -2600,9 +2606,9 @@ file attribute view.
 |=======================================================================
 
 [#TriggeringPolicies]
-== TriggeringPolicies
+=== TriggeringPolicies
 
-=== Composite Triggering Policy
+==== Composite Triggering Policy
 
 The `CompositeTriggeringPolicy` combines multiple triggering policies and returns true if any of the configured policies return true.
 The
@@ -2619,7 +2625,7 @@ For example, the following XML fragment defines policies that rollover the log w
 </Policies>
 ----
 
-=== Cron Triggering Policy
+==== Cron Triggering Policy
 
 The `CronTriggeringPolicy` triggers rollover based on a cron expression.
 This policy is controlled by a timer and is asynchronous in processing log events, so it is possible that log events from the previous or next period may appear at the beginning or end of the log file.
@@ -2640,7 +2646,7 @@ expression indicates a rollover should have occurred between that time
 and the current time the file will be immediately rolled over.
 |=======================================================================
 
-=== OnStartup Triggering Policy
+==== OnStartup Triggering Policy
 
 The `OnStartupTriggeringPolicy` policy causes a rollover if the log file is older than the current JVM's start time and the minimum file size is met or exceeded.
 
@@ -2660,7 +2666,7 @@ When running in Google App Engine, the OnStartup policy causes a rollover if the
 and falls back to Log4J initialization time instead.)
 
 [#sizebased-triggering-policy]
-=== SizeBased Triggering Policy
+==== SizeBased Triggering Policy
 
 The `SizeBasedTriggeringPolicy` causes a rollover once the file has reached the specified size.
 The size can be specified in bytes, with the suffix KB, MB, GB, or TB for example `20MB`.
@@ -2672,7 +2678,7 @@ Otherwise, the target file will be overwritten on every rollover as the SizeBase
 When used without a time-based triggering policy the SizeBased Triggering Policy will cause the timestamp value to change.
 
 [#timebased-triggering-policy]
-=== TimeBased Triggering Policy
+==== TimeBased Triggering Policy
 
 The `TimeBasedTriggeringPolicy` causes a rollover once the date/time pattern no longer applies to the active file.
 This policy accepts an
@@ -2701,10 +2707,10 @@ load of doing so across time.
 |=======================================================================
 
 [#RolloverStrategies]
-== RolloverStrategies
+=== RolloverStrategies
 
 [#DefaultRolloverStrategy]
-=== DefaultRolloverStrategy
+==== DefaultRolloverStrategy
 
 Default Rollover Strategy
 
@@ -2798,7 +2804,7 @@ archived log file during compression.
 |=======================================================================
 
 [#DirectWriteRolloverStrategy]
-=== DirectWriteRolloverStrategy
+==== DirectWriteRolloverStrategy
 
 DirectWrite Rollover Strategy
 
@@ -2959,7 +2965,7 @@ This sample configuration is the same as the previous one but limits the number
 ----
 
 [#CustomDeleteOnRollover]
-=== CustomDeleteOnRollover
+==== CustomDeleteOnRollover
 
 Log Archive Retention Policy: Delete on Rollover
 
@@ -3045,7 +3051,7 @@ and must return a list with the paths to delete.
 |=======================================================================
 
 [#DeleteIfFileName]
-== DeleteIfFileName
+=== DeleteIfFileName
 
 .IfFileName Condition Parameters
 [cols="20%,20%,60%",options="header",]
@@ -3071,7 +3077,7 @@ the path name matches).
 |=======================================================================
 
 [#DeleteIfLastModified]
-== DeleteIfLastModified
+=== DeleteIfLastModified
 
 .IfLastModified Condition Parameters
 [cols="20%,20%,60%",options="header",]
@@ -3090,7 +3096,7 @@ the file is old enough).
 |=======================================================================
 
 [#DeleteIfAccumulatedFileCount]
-== DeleteIfAccumulatedFileCount
+=== DeleteIfAccumulatedFileCount
 
 .IfAccumulatedFileCount Condition Parameters
 [cols="20%,20%,60%",options="header",]
@@ -3107,7 +3113,7 @@ the threshold count has been exceeded).
 |=======================================================================
 
 [#DeleteIfAccumulatedFileSize]
-== DeleteIfAccumulatedFileSize
+=== DeleteIfAccumulatedFileSize
 
 .IfAccumulatedFileSize Condition Parameters
 [cols="20%,20%,60%",options="header",]
@@ -3201,7 +3207,7 @@ During every rollover, this configuration will delete files that match "*/app-*.
 ----
 
 [#ScriptCondition]
-== ScriptCondition
+=== ScriptCondition
 
 .ScriptCondition Parameters
 [cols="20%,20%,60%",options="header",]
@@ -3216,7 +3222,7 @@ how ScriptFiles and ScriptRefs can be configured.
 |=======================================================================
 
 [#ScriptParameters]
-== ScriptParameters
+=== ScriptParameters
 
 .Script Parameters
 [cols="20%,20%,60%",options="header",]
@@ -3306,7 +3312,7 @@ The Delete action will delete all files returned by the script.
 ----
 
 [#CustomPosixViewAttributeOnRollover]
-== CustomPosixViewAttributeOnRollover
+=== CustomPosixViewAttributeOnRollover
 
 Log Archive File Attribute View Policy: Custom file attribute on Rollover
 
@@ -3397,7 +3403,7 @@ Below is a sample configuration that uses a RollingFileAppender and defines diff
 ----
 
 [#RollingRandomAccessFileAppender]
-== RollingRandomAccessFileAppender
+=== RollingRandomAccessFileAppender
 
 The RollingRandomAccessFileAppender is similar to the standard
 <<RollingFileAppender>> except it is always buffered (this cannot be switched off) and internally it uses a
@@ -3509,11 +3515,11 @@ file attribute view.
 
 |=======================================================================
 
-=== Triggering Policies
+==== Triggering Policies
 
 See <<TriggeringPolicies,RollingFileAppender Triggering Policies>>.
 
-=== Rollover Strategies
+==== Rollover Strategies
 
 See <<RolloverStrategies,`RollingFileAppender` rollover strategies>>.
 
@@ -3597,7 +3603,7 @@ Below is a sample configuration that uses a RollingRandomAccessFileAppender with
 ----
 
 [#RoutingAppender]
-== RoutingAppender
+=== RoutingAppender
 
 The `RoutingAppender` evaluates LogEvents and then routes them to a subordinate Appender.
 The target Appender may be an appender previously configured and may be referenced by its name or the Appender can be dynamically created as needed.
@@ -3676,7 +3682,7 @@ Note that the List Appender is one of our test appenders, any appender can be us
 ----
 
 [#Routes]
-=== Routes
+==== Routes
 
 The `Routes` element accepts a single attribute named "pattern".
 The pattern is evaluated against all the registered Lookups and the result is used to select a `Route`.
@@ -3761,7 +3767,7 @@ In this example, the script runs for each log event and picks a route based on t
 ----
 
 [#Purge]
-=== Purge Policy
+==== Purge Policy
 
 The RoutingAppender can be configured with a PurgePolicy whose purpose is to stop and remove dormant Appenders that have been dynamically created by the RoutingAppender.
 Log4j currently provides the IdlePurgePolicy is the only PurgePolicy available for cleaning up the Appenders.
@@ -3805,7 +3811,7 @@ Note that the AuditAppender was predefined while the RollingFileAppenders are cr
 ----
 
 [[SMTPAppender]]
-== SMTPAppender
+=== SMTPAppender
 
 Sends an e-mail when a specific logging event occurs, typically on errors or fatal errors.
 
@@ -3914,7 +3920,7 @@ As with other Appenders, the formatting can be controlled by specifying a Layout
 ----
 
 [#ScriptAppenderSelector]
-== ScriptAppenderSelector
+=== ScriptAppenderSelector
 
 When the configuration is built, the `ScriptAppenderSelector` appender calls a `ScriptPlugin` to compute an appender name.
 Log4j then creates one of the appender named listed under `AppenderSet` using the name of the
@@ -3950,7 +3956,7 @@ The appender name is recorded under the name of the
 ----
 
 [#SocketAppender]
-== SocketAppender
+=== SocketAppender
 
 The `SocketAppender` is an OutputStreamAppender that writes its output to a remote destination specified by a host and port.
 The data can be sent over either TCP or UDP and can be sent in any format.
@@ -4060,7 +4066,7 @@ This is a secured <<SSL>> configuration:
 ----
 
 [#SSL]
-== SSL
+=== SSL
 
 Several appenders can be configured to use either a plain network connection or a Secure Socket Layer (SSL) connection.
 This section documents the parameters available for SSL configuration.
@@ -4083,7 +4089,7 @@ counterparty. Determines whether the remote authentication credentials
 |=======================================================================
 
 [#KeyStore]
-=== KeyStore
+==== KeyStore
 
 The Keystore is meant to contain your private keys and certificates, and determines which authentication credentials to send to the remote host.
 
@@ -4116,7 +4122,7 @@ algorithms].
 |=======================================================================
 
 [#TrustStore]
-=== TrustStore
+==== TrustStore
 
 The trust store is meant to contain the CA certificates you are willing to trust when a remote party presents its certificate.
 Determines whether the remote authentication credentials (and thus the connection) should be trusted.
@@ -4152,7 +4158,7 @@ algorithms].
 |=======================================================================
 
 [#Example]
-=== Example
+==== Example
 
 [source,xml]
 ----
@@ -4163,7 +4169,7 @@ algorithms].
 ----
 
 [#SyslogAppender]
-== SyslogAppender
+=== SyslogAppender
 
 The `SyslogAppender` is a `SocketAppender` that writes its output to a remote destination specified by a host and port in a format that conforms with either the BSD Syslog format or the RFC 5424 format.
 The data can be sent over either TCP or UDP.
@@ -4329,7 +4335,7 @@ For <<SSL>> this appender writes its output to a remote destination specified by
 ----
 
 [[JeroMQAppender]]
-== ZeroMQ/JeroMQ Appender
+=== ZeroMQ/JeroMQ Appender
 
 The ZeroMQ appender uses the https://github.com/zeromq/jeromq[JeroMQ] library to send log events to one or more ZeroMQ endpoints.
 
@@ -4460,3 +4466,44 @@ Please consult the JeroMQ and ZeroMQ documentation for details.
 |boolean
 |The ZMQ_XPUB_VERBOSE option. Defaults to false.
 |===
+
+[#extending]
+== Extending
+
+Appenders are xref:manual/plugins.adoc[plugins] implementing link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html[the `Appender` interface].
+This section will guide you on how to create custom ones.
+
+[WARNING]
+====
+*Implementing a reliable and efficient appender is a difficult task!*
+We strongly advise you to
+
+. Use existing appenders and/or managers whenever appropriate
+. Share your use case and ask for feedback in a {logging-services-url}/support.html[user support channel]
+====
+
+[#extending-plugins]
+=== Plugin preliminaries
+
+include::partial$manual/plugin-preliminaries.adoc[]
+
+[#extending-appenders]
+=== Extending appenders
+
+Appenders are xref:manual/plugins.adoc[plugins] implementing link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html[the `Appender` interface].
+We recommend users to extend from link:../javadoc/log4j-core/org/apache/logging/log4j/core/appender/AbstractAppender.html[`AbstractAppender`], which provides implementation convenience.
+While annotating your appender with `@Plugin`, you need to make sure that
+
+* It has a unique `name` attribute across all available `Appender` plugins
+* The `category` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`]
+
+Most appender implementation use *managers*, which model an abstraction owning the resources, such as an `OutputStream` or a socket.
+When a reconfiguration occurs a new appender will be created.
+However, if nothing significant in the previous manager has changed, the new appender will simply reference it instead of creating a new one.
+This ensures that events are not lost while a reconfiguration is taking place without requiring that logging pause while the reconfiguration takes place.
+You are strongly advised to study the manager concept in <<collection,the predefined appenders>>, and either use an existing manager, or create your own.
+
+You can check out following files for examples:
+
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/HttpAppender.java[`HttpAppender.java`] – <<HttpAppender>> sends log events over HTTP using `HttpURLConnectionManager`
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java[`ConsoleAppender.java`] – <<ConsoleAppender>> writes log events to either `System.out` or `System.err` using `OutputStreamManager`
diff --git a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
index 448b392573..b97b63502b 100644
--- a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
+++ b/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
-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].
-
-=== 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
-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
+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 link:../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]
+== `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
+}
+
+Configuration --> "0..*" Filter
 
-=== 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..*" 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`
+| -
+| -
+| -
+| -
+| -
+| ✅
 |===
+====
+
+[#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]
+== `Layout`
 
-More often than not, users wish to customize not only the output
-destination but also the output format. This is accomplished by
-associating a
-link:../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.
+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.
 
-For example, the PatternLayout with the conversion pattern "%r [%t] %-5p
-%c - %m%n" will output something akin to:
+[#Layout-diagram]
+.`Layout` and other directly related classes
+[plantuml]
+....
+@startuml
+
+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/config-intro.adoc b/src/site/antora/modules/ROOT/pages/manual/config-intro.adoc
index 90bf892d86..10a7f64378 100644
--- a/src/site/antora/modules/ROOT/pages/manual/config-intro.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/config-intro.adoc
@@ -17,17 +17,10 @@
 [id=configuration]
 = Configuration
 
-Logging is a standard method for monitoring the health of an application and diagnosing problems that may arise within it.
 Even moderately sized applications can contain thousands of logging statements.
+To decide which of these statements will be logged and where, users need to configure Log4j Core in one of following ways:
 
-To decide which of these statements will be logged and where, users need to configure Log4j Core in one of two ways:
+* Through a xref:manual/configuration.adoc[configuration file]
+* Through xref:manual/customconfig.adoc[programmatic configuration]
 
-* through a xref:manual/configuration.adoc[].
-Since version 2.0, the configuration file format has been considered part of the public API and has remained stable across significant version upgrades.
-
-* through xref:manual/customconfig.adoc[Programmatic Configuration], which provides a larger spectrum of possible customizations but might require code changes during version upgrades.
-
-[NOTE]
-====
-To prevent a chicken-and-egg problem, users can only supply some configuration options (e.g., the configuration file location) through xref:manual/systemproperties.adoc[configuration properties].
-====
\ No newline at end of file
+Some meta-configuration options (e.g., the configuration file location) are only available through xref:manual/systemproperties.adoc[system properties].
diff --git a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
index 3ae2eb6af2..388deed0dc 100644
--- a/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/configuration.adoc
@@ -17,100 +17,94 @@
 [#configuration-file]
 = Configuration file
 
-Users can configure Log4j Core using different file formats.
-The `log4j-core` artifact includes XML, JSON, YAML, and Java properties formats factories. 
+Using a configuration file is the most popular and recommended approach for configuring Log4j Core.
+In this page we will examine the composition of a configuration file and how Log4j Core uses it.
 
-As detailed in the table below, some configuration formats require additional dependencies on the classpath.
-
-include::partial$configuration-file-format-deps.adoc[]
-
-[WARNING]
+[TIP]
 ====
-The format of the configuration file changed between Log4j{nbsp}1 and Log4j{nbsp}2.
-Files in the Log4j{nbsp}1 format are ignored by default.
-
-To enable partial support for old configuration formats, see xref:manual/migration.adoc#ConfigurationCompatibility[configuration compatibility].
+If you are looking for a quick start on using Log4j in your application or library, please refer to xref:manual/getting-started.adoc[] instead.
 ====
 
 [id=automatic-configuration]
 == [[AutomaticConfiguration]] Configuration file location
 
-Upon initialization of a new logger context, Log4j assigns it a context name and scans the following **classpath** locations for a configuration file:
+Upon initialization of a new xref:manual/architecture.adoc#LoggerContext[logger context, the anchor of the logging implementation], Log4j Core assigns it a context name and scans the following **classpath** locations for a configuration file in following order:
 
 . Files named `log4j2-test<contextName>.<extension>`
-. Files named `log4j2-test.<extension>`,
+. Files named `log4j2-test.<extension>`
 . Files named `log4j2<contextName>.<extension>`
-. Files named `log4j2.<extension>`,
-. If no configuration file is found, Log4j uses the
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/DefaultConfiguration.html[`DefaultConfiguration`]
-and the xref:manual/status-logger.adoc[status logger] prints a warning.
-The default configuration prints all messages less specific than
-xref:manual/systemproperties.adoc#log4j2.level[`log4j2.level`]
-to the console.
+. Files named `log4j2.<extension>`
 
-[WARNING]
-====
-The configuration files prefixed by `log4j2-test` should only be used on the test classpath.
+The `<contextName>` and `<extension>` placeholders above have the following meaning
 
-If multiple configuration files in the same category are found, Log4j uses a deterministic order to choose one of them (see
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Order.html[`@Order`]).
+<contextName>::
+A name derived from the runtime environment:
++
+* For standalone Java SE applications, it is a random identifier.
+* For web applications, it is an identifier derived from the application descriptor.
+See xref:manual/webapp.adoc#configuration[Log4j Web application configuration] for details.
 
-Nevertheless:
+<extension>::
+A file extension supported by a `ConfigurationFactory`.
+The order in which an extension will be searched for first depends on the order of the associated `ConfigurationFactory`.
+See <<configuration-factories>> for details.
 
-* If you're developing an app, don't use config files with different extensions.
-* If you're developing a library, only add config files to your test classpath.
-====
+If no configuration file is found, Log4j Core uses the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/DefaultConfiguration.html[`DefaultConfiguration`] and the xref:manual/status-logger.adoc[status logger] prints a warning.
+The default configuration prints all messages less specific than xref:manual/systemproperties.adoc#log4j2.level[`log4j2.level`] to the console.
 
-The `<contextName>` and `<extension>` placeholders above have the following meaning
+You can override the location of the configuration file using the xref:manual/systemproperties.adoc#log4j2.configurationFile[the `log4j2.configurationFile` system property].
+In such a case, Log4j Core will guess the configuration file format from the provided file name, or use the default configuration factory if the extension is unknown.
 
-<contextName>:: depends on the runtime environment in which Log4j runs:
+There are certain *best-practices* we strongly recommend you to adapt in your Log4j configuration:
 
-* for standalone Java SE applications, it is a random identifier,
-* for web applications, it is derived from the application descriptor.
-See xref:manual/webapp.adoc#configuration[Log4j
- Web application configuration] for more details.
+* Files prefixed by `log4j2-test` should only be used on the test classpath.
+* If you are developing an application, don't use multiple Log4j configuration files with same name, but different extensions.
+That is, don't provide both `log4j2.xml` and `log4j2.json` files.
+* If you are developing a library, only add configuration files to your test classpath.
 
-<extension>:: must be one of the file extensions assigned to a configuration file format:
-+
-[cols="1,1"]
+[#configuration-factories]
+=== Predefined ``ConfigurationFactory`` plugins
+
+Log4j Core uses plugins extending from link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`] to determine which configuration file extensions are supported, in which order, and how to read them.
+How this works under the hood and how you can introduce your custom implementations is explained in <<ConfigurationFactory>>.
+
+.Supported configuration file formats by predefined `ConfigurationFactory` plugins
+[%header,cols="1,1m,1"]
+|===
+| File format | Extension | Order
+| XML | xml | 5
+| JSON | json, jsn | 6
+| YAML | yaml, yml | 7
+| Properties | properties | 8
 |===
-| Configuration file format | Extension
 
-| XML
-| `xml`
+Note that `ConfigurationFactory` plugins will be employed in descending order.
+That is, for instance, XML file format will be checked last, as a fallback.
 
-| JSON
-| `json` or `jsn`
+Some `ConfigurationFactory` plugins require additional dependencies on the classpath:
 
-| YAML
-| `yaml` or `yml`
+include::partial$configuration-file-format-deps.adoc[]
 
-|Java properties
-| `properties`
-|===
+[id=configuration-syntax]
+== [[ConfigurationSyntax]] Syntax
 
 [NOTE]
 ====
-It is also possible to override the location of the configuration file using the
-xref:manual/systemproperties.adoc#log4j2.configurationFile[`log4j2.configurationFile`]
-configuration property.
-In this case, Log4j will guess the configuration file format from the provided configuration file extension or use the default configuration factory if the extension is unknown.
-
-See xref:manual/systemproperties.adoc#log4j2.configurationFile[`log4j2.configurationFile`] for details.
+Starting with Log4j 2, the configuration file syntax has been considered part of the public API and has remained stable across significant version upgrades.
 ====
 
-[id=configuration-syntax]
-== [[ConfigurationSyntax]] Syntax
+[WARNING]
+====
+The syntax of the configuration file changed between Log4j{nbsp}1 and Log4j{nbsp}2.
+Files in the Log4j{nbsp}1 syntax are ignored by default.
+To enable partial support for old configuration syntax, see xref:manual/migration.adoc#ConfigurationCompatibility[configuration compatibility].
+====
 
 The Log4j runtime is composed of xref:manual/plugins.adoc[plugins], which are like beans in the Spring Framework and Java EE.
 Appenders, layouts, filters, configuration loaders, and similar components are all accessed as plugins.
 
-All configuration files are represented internally as a tree of
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html[`Node`]s,
-which is translated into a tree of Log4j plugins.
-The tree's root creates a
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]
-object.
+All configuration files are represented internally as a tree of link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html[`Node`]s, which is translated into a tree of Log4j plugins.
+The tree's root creates a link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`] object.
 
 A node is a relatively simple structure representing a single Log4j plugin (see xref:plugin-reference.adoc[] for a complete list), such as an appender, layout, or logger configuration.
 
@@ -409,11 +403,6 @@ Overrides the logging level of xref:manual/status-logger.adoc[].
 Since version `2.24.0`, this attribute is deprecated and should be replaced with the xref:manual/status-logger.adoc#log4j2.statusLoggerLevel[log4j2.statusLoggerLevel] configuration property instead.
 ====
 
-[id=configuration-elements-filters]
-=== Filters
-
-See xref:manual/filters.adoc#filters[Filters] for additional filtering capabilities that can be applied to the global configuration object.
-
 [id=configuring-loggers]
 == [[Loggers]] Loggers
 
@@ -441,7 +430,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:
 
@@ -1076,40 +1065,17 @@ include::example$manual/configuration/arbiters-select.properties[tag=select]
 <2> Otherwise, a JSON Template Layout will be used.
 
 [#CompositeConfiguration]
-== Composite Configuration
-
-Log4j allows multiple configuration files to be used at the same time by specifying them as a list of comma-separated file paths or URLs in the
-xref:manual/systemproperties.adoc#log4j2.configurationFile[`log4j2.configurationFile`]
-configuration property.
-
-These configuration files are merged into a single configuration file using
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/composite/MergeStrategy.html[`MergeStrategy`]
-service that can be customized using the
-xref:manual/systemproperties.adoc#log4j2.mergeStrategy[`log4j2.mergeStrategy`]
-configuration property.
-
-The default merge strategy will merge the files using the following rules:
-
-. <<global-configuration-attributes>> in later configurations replace those in previous configurations.
-+
-The exception is the `monitorInterval` attribute: the lowest positive value from all the configuration files will be used.
+== Composite configuration
 
-. <<property-substitution,Properties>> from all configurations are aggregated.
-Duplicate properties replace those in previous configurations.
+include::partial$manual/composite-configuration.adoc[tag=intro]
 
-. xref:manual/filters.adoc[Filters] are aggregated under
-xref:manual/filters.adoc#CompositeFilter[CompositeFilter], if more than one filter is defined.
+You can provide a list of comma-separated file paths or URLs in xref:manual/systemproperties.adoc#log4j2.configurationFile[the `log4j2.configurationFile` configuration property], where each resource will get read into a `Configuration`, and then eventually combined into a single one using link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.html[`CompositeConfiguration`].
 
-. xref:manual/scripts.adoc[] are aggregated.
-Duplicate definitions replace those in previous configurations.
-
-. xref:manual/appenders.adoc[Appenders] are aggregated.
-Appenders with the same name are **replaced** by those in later configurations, including all their elements.
-
-. <<configuring-loggers,Loggers>> are all aggregated.
-Logger attributes are individually merged, and those in later configurations replace duplicates.
-Appender references on a logger are aggregated, and those in later configurations replace duplicates.
-The strategy merges filters on loggers using the rule above.
+.How does `CompositeConfiguration` work?
+[%collapsible]
+====
+include::partial$manual/composite-configuration.adoc[tag=how]
+====
 
 [id=format-specific-notes]
 == Format specific notes
@@ -1233,3 +1199,39 @@ rootLogger.appenderRef.0.ref = APPENDER
 . All the keys of the form `logger.<name>.appenderRef.<id>`, where `<name>` and `<id>` are arbitrary, are considered appender references.
 
 . To add a filter to a component use a `filter.<id>` prefix instead of just `<id>`.
+
+[#extending]
+== Extending
+
+Log4j Core uses xref:manual/plugins.adoc[plugins] to inject necessary components while reading a configuration file.
+In this section, we will explore extension points users can hook into to customize the way Log4j Core reads configuration files.
+
+[#extending-plugins]
+=== Plugin preliminaries
+
+include::partial$manual/plugin-preliminaries.adoc[]
+
+[#ConfigurationFactory]
+=== Extending `ConfigurationFactory` plugins
+
+Under the hood, Log4j Core uses plugins extending from link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`] to load configuration files.
+This procedure can be summarized as follows:
+
+. Load plugins which extend from link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`] and whose plugin `category` is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html#CATEGORY[`ConfigurationFactory.CATEGORY`]
+. Sort them by link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Order.html[`@Order`] annotation (in decreasing value order), if present
+. Feed <<automatic-configuration,found configuration files>> to `ConfigurationFactory` instances in order, if the file extension is contained by `String[]` returned from link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html#getSupportedTypes()[`ConfigurationFactory#getSupportedTypes()`]
+
+If xref:manual/systemproperties.adoc#log4j2.configurationFactory[the `log4j2.configurationFactory` system property] is defined, it will be used before any other factory implementations.
+
+For an example, see {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/config/json/JsonConfigurationFactory.java[`JsonConfigurationFactory.java`] on how Log4j Core implements JSON-formatted configuration file read.
+
+[TIP]
+====
+Next to introducing new configuration file formats, `ConfigurationFactory` can be used for xref:manual/customconfig.adoc[programmatic configuration] too.
+====
+
+[#extending-config-file-plugins]
+=== Plugins represented in a configuration file
+
+As explained in <<configuration-syntax>>, a configuration file gets parsed into a tree of plugins.
+If your plugin needs to be represented in a configuration file element, some xref:manual/plugins.adoc#core[extra plugin configuration] needs to be administered.
diff --git a/src/site/antora/modules/ROOT/pages/manual/customconfig.adoc b/src/site/antora/modules/ROOT/pages/manual/customconfig.adoc
index 0662519d88..fc7f00881d 100644
--- a/src/site/antora/modules/ROOT/pages/manual/customconfig.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/customconfig.adoc
@@ -14,372 +14,236 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
-= Programmatic Configuration
+= Programmatic configuration
 
-Log4j 2 provides a few ways for applications to create their own
-programmatic configuration:
+Next to xref:manual/configuration.adoc[configuration files], Log4j Core can be configured programmatically too.
+In this page, we will explore utilities helping with programmatic configuration and demonstrate how they can be leveraged for certain use cases.
 
-* Specify a custom `ConfigurationFactory` to start Log4j with a
-programmatic configuration
-* Use the `Configurator` to replace the configuration after Log4j started
-* Initialize Log4j with a combination of a configuration file and
-programmatic configuration
-* Modify the current `Configuration` after initialization
+[#prelim]
+== Preliminaries
+
+To begin with, we strongly encourage you to check out the xref:manual/architecture.adoc[] page first.
+Let's repeat some basic definitions of particular interest:
+
+xref:manual/architecture.adoc#LoggerContext[`LoggerContext`]::
+It is the anchor of the logging system.
+Generally there is one, statically-accessible, global `LoggerContext` for most applications.
+But there can be multiple ``LoggerContext``s, for instance, to use in tests, in Java EE web applications, etc.
+
+xref:manual/architecture.adoc#Configuration[`Configuration`]::
+It encapsulates a Log4j Core configuration (properties, appenders, loggers, etc.) and is associated with a `LoggerContext`.
+
+[#tooling]
+== Tooling
+
+For programmatic configuration, Log4j Core essentially provides the following tooling:
+
+<<ConfigurationBuilder>>:: for declaratively creating a `Configuration`
+
+<<Configurator>>:: for associating a `Configuration` with a `LoggerContext`
+
+<<ConfigurationFactory>>:: for registering a `Configuration` factory to xref:manual/configuration.adoc[the configuration file mechanism]
+
+In short, we will create ``Configuration``s using `ConfigurationBuilder`, and activate them using `Configurator`.
 
 [#ConfigurationBuilder]
-== The ConfigurationBuilder API
-
-Starting with release 2.4, Log4j provides a `ConfigurationBuilder` and a
-set of component builders that allow a `Configuration` to be created
-fairly easily. Actual configuration objects like `LoggerConfig` or
-`Appender` can be unwieldy; they require a lot of knowledge about Log4j
-internals which makes them difficult to work with if all you want is to
-create a `Configuration`.
-
-The new `ConfigurationBuilder` API (in the
-`org.apache.logging.log4j.core.config.builder.api` package) allows users
-to create Configurations in code by constructing component
-_definitions_. There is no need to work directly with actual
-configuration objects. Component definitions are added to the
-`ConfigurationBuilder`, and once all the definitions have been collected
-all the actual configuration objects (like Loggers and Appenders) are
-constructed.
-
-`ConfigurationBuilder` has convenience methods for the base components
-that can be configured such as Loggers, Appenders, Filter, Properties,
-etc. However, Log4j 2's plugin mechanism means that users can create any
-number of custom components. As a trade-off, the `ConfigurationBuilder`
-API provides only a limited number of "strongly typed" convenience
-methods like `newLogger()`, `newLayout()` etc. The generic
-`builder.newComponent()` method can be used if no convenience method
-exists for the component you want to configure.
-
-For example, the builder does not know what sub-components can be
-configured on specific components such as the RollingFileAppender vs.
-the RoutingAppender. To specify a triggering policy on a
-RollingFileAppender you would use builder.newComponent().
-
-Examples of using the `ConfigurationBuilder` API are in the sections that
-follow.
+=== `ConfigurationBuilder`
 
-[#ConfigurationFactory]
-== Understanding ConfigurationFactory
-
-During initialization, Log4j 2 will search for available
-xref:manual/extending.adoc#ConfigurationFactory[ConfigurationFactories] and
-then select the one to use. The selected `ConfigurationFactory` creates
-the `Configuration` that Log4j will use. Here is how Log4j finds the
-available ConfigurationFactories:
-
-1.  A system property named `log4j2.configurationFactory` can be set
-with the name of the ConfigurationFactory to be used.
-2.  `ConfigurationFactory.setConfigurationFactory(ConfigurationFactory)`
-can be called with the instance of the `ConfigurationFactory` to be used.
-This must be called before any other calls to Log4j.
-3.  A `ConfigurationFactory` implementation can be added to the classpath
-and configured as a plugin in the "ConfigurationFactory" category. The
-`@Order` annotation can be used to specify the relative priority when
-multiple applicable ConfigurationFactories are found.
-
-ConfigurationFactories have the concept of "supported types", which
-basically maps to the file extension of the configuration file that the
-ConfigurationFactory can handle. If a configuration file location is
-specified, ConfigurationFactories whose supported type does not include
-"*" or the matching file extension will not be used.
-
-[#Example]
-== Initialize Log4j Using ConfigurationBuilder with a Custom ConfigurationFactory
-
-One way to programmatically configure Log4j 2 is to create a custom
-`ConfigurationFactory` that uses the
-<<ConfigurationBuilder,`ConfigurationBuilder`>> to create a
-Configuration. The below example overrides the `getConfiguration()`
-method to return a `Configuration` created by the `ConfigurationBuilder`.
-This will cause the `Configuration` to automatically be hooked into Log4j
-when the `LoggerContext` is created. In the example below, because it
-specifies a supported type of "*" it will override any configuration
-files provided.
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.html[`ConfigurationBuilder`] interface models a fluent API to programmatically create link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]s.
+If you have ever created a xref:manual/configuration.adoc[Log4j Core configuration file], consider `ConfigurationBuilder` as a convenience utility to model the very same declarative configuration structure programmatically.
+
+Let's show `ConfigurationBuilder` usage with an example.
+Consider the following Log4j Core configuration file:
+
+[tabs]
+====
+XML::
++
+.Snippet from an example {antora-examples-url}/manual/customconfig/ConfigurationBuilder/log4j2.xml[`log4j2.xml`]
+[source,xml]
+----
+include::example$manual/customconfig/ConfigurationBuilder/log4j2.xml[lines=24..34,indent=0]
+----
+
+JSON::
++
+.Snippet from an example {antora-examples-url}/manual/customconfig/ConfigurationBuilder/log4j2.json[`log4j2.json`]
+[source,json]
+----
+include::example$manual/customconfig/ConfigurationBuilder/log4j2.json[lines=3..16,indent=0]
+----
+
+YAML::
++
+.Snippet from an example {antora-examples-url}/manual/customconfig/ConfigurationBuilder/log4j2.yaml[`log4j2.yaml`]
+[source,yaml]
+----
+include::example$manual/customconfig/ConfigurationBuilder/log4j2.yaml[lines=19..-1,indent=0]
+----
 
+Properties::
++
+.Snippet from an example {antora-examples-url}/manual/customconfig/ConfigurationBuilder/log4j2.properties[`log4j2.properties`]
+[source,properties]
+----
+include::example$manual/customconfig/ConfigurationBuilder/log4j2.properties[lines=17..-1]
+----
+====
+
+Above Log4j Core configuration can be programmatically built using `ConfigurationBuilder` as follows:
+
+.Snippet from an example {antora-examples-url}/manual/customconfig/Usage.java[`Usage.java`]
 [source,java]
 ----
-@Namespace(ConfigurationFactory.NAMESPACE)
-@Plugin
-@Order(50)
-public class CustomConfigurationFactory extends ConfigurationFactory {
-
-    static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
-        builder.setConfigurationName(name);
-        builder.setStatusLevel(Level.ERROR);
-        builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL).
-            addAttribute("level", Level.DEBUG));
-        AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
-            addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
-        appenderBuilder.add(builder.newLayout("PatternLayout").
-            addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
-        appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
-            Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
-        builder.add(appenderBuilder);
-        builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
-            add(builder.newAppenderRef("Stdout")).
-            addAttribute("additivity", false));
-        builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
-        return builder.build();
-    }
-
-    @Override
-    public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
-        return getConfiguration(loggerContext, source.toString(), null);
-    }
-
-    @Override
-    public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
-        ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
-        return createConfiguration(name, builder);
-    }
-
-    @Override
-    protected String[] getSupportedTypes() {
-        return new String[] {"*"};
-    }
-}
+include::example$manual/customconfig/Usage.java[tag=createConfiguration,indent=0]
 ----
+<1> The default `ConfigurationBuilder` instance is obtained using link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilderFactory.html#newConfigurationBuilder()[`ConfigurationBuilderFactory.newConfigurationBuilder()`] static method
+<2> Add the appender along with the layout
+<3> Add the root logger along with a level and appender reference
+<4> Create the configuration, but *don't initialize* it
++
+[TIP]
+====
+It is a good practice to not initialize ``Configuration``s when they are constructed.
+This task should ideally be delegated to <<Configurator>>.
+====
+
+`ConfigurationBuilder` has convenience methods for the base components that can be configured such as loggers, appenders, filters, properties, etc.
+Though there are cases where the provided convenience methods fall short of:
 
-As of version 2.7, the `ConfigurationFactory.getConfiguration()` methods
-take an additional `LoggerContext` parameter.
+* Custom xref:manual/plugins.adoc#core[plugins that are declared to be represented in a configuration]
+* Custom subcomponents (e.g., a xref:manual/appenders.adoc#TriggeringPolicies[triggering policy] for xref:manual/appenders.adoc#RollingFileAppender[`RollingFileAppender`])
+
+For those, you can use the generic link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.html#newComponent()[`ConfigurationBuilder#newComponent()`] method.
+
+See {project-github-url}/log4j-core-test/src/test/java/org/apache/logging/log4j/core/config/Configurator1Test.java[`Configurator1Test.java`] for examples on `ConfigurationBuilder`, `newComponent()`, etc. usage.
 
 [#Configurator]
-== Reconfigure Log4j Using ConfigurationBuilder with the Configurator
+=== `Configurator`
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configurator.html[`Configurator`] is a programmatic interface to associate a ``Configuration`` with either new, or an existing `LoggerContext`.
 
-An alternative to a custom `ConfigurationFactory` is to configure with the
-`Configurator`. Once a `Configuration` object has been constructed, it can
-be passed to one of the `Configurator.initialize` methods to set up the
-Log4j configuration.
+[#Configurator-initialize]
+==== Obtaining a `LoggerContext`
 
-Using the `Configurator` in this manner allows the application control
-over when Log4j is initialized. However, should any logging be attempted
-before `Configurator.initialize()` is called then the default
-configuration will be used for those log events.
+You can use `Configurator` to obtain a `LoggerContext`:
 
+.Snippet from an example {antora-examples-url}/manual/customconfig/Usage.java[`Usage.java`]
 [source,java]
 ----
-ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
-builder.setStatusLevel(Level.ERROR);
-builder.setConfigurationName("BuilderTest");
-builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
-    .addAttribute("level", Level.DEBUG));
-AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
-    ConsoleAppender.Target.SYSTEM_OUT);
-appenderBuilder.add(builder.newLayout("PatternLayout")
-    .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
-appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY, Filter.Result.NEUTRAL)
-    .addAttribute("marker", "FLOW"));
-builder.add(appenderBuilder);
-builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG)
-    .add(builder.newAppenderRef("Stdout")).addAttribute("additivity", false));
-builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
-ctx = Configurator.initialize(builder.build());
+include::example$manual/customconfig/Usage.java[tag=useConfiguration,indent=0]
 ----
 
-This example shows how to create a configuration that includes a
-RollingFileAppender.
+`initialize()` will either return the `LoggerContext` currently associated with the caller, or create a new one.
+This is a convenient way to create isolated ``LoggerContext``s for tests, etc.
+
+[#Configurator-reconfigure]
+==== Reconfiguring the active `LoggerContext`
+
+You can use `Configurator` to reconfigure the active `LoggerContext` as follows:
 
+.Snippet from an example {antora-examples-url}/manual/customconfig/Usage.java[`Usage.java`]
 [source,java]
 ----
-ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
-
-builder.setStatusLevel(Level.ERROR);
-builder.setConfigurationName("RollingBuilder");
-// create a console appender
-AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
-    ConsoleAppender.Target.SYSTEM_OUT);
-appenderBuilder.add(builder.newLayout("PatternLayout")
-    .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
-builder.add(appenderBuilder);
-// create a rolling file appender
-LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
-    .addAttribute("pattern", "%d [%t] %-5level: %msg%n");
-ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
-    .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
-    .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
-appenderBuilder = builder.newAppender("rolling", "RollingFile")
-    .addAttribute("fileName", "target/rolling.log")
-    .addAttribute("filePattern", "target/archive/rolling-%d{MM-dd-yy}.log.gz")
-    .add(layoutBuilder)
-    .addComponent(triggeringPolicy);
-builder.add(appenderBuilder);
-
-// create the new logger
-builder.add(builder.newLogger("TestLogger", Level.DEBUG)
-    .add(builder.newAppenderRef("rolling"))
-    .addAttribute("additivity", false));
-
-builder.add(builder.newRootLogger(Level.DEBUG)
-    .add(builder.newAppenderRef("rolling")));
-LoggerContext ctx = Configurator.initialize(builder.build());
+include::example$manual/customconfig/Usage.java[tag=reconfigureActiveLoggerContext,indent=0]
 ----
 
-[#Hybrid]
-== Initialize Log4j by Combining Configuration File with Programmatic Configuration
+Using the `Configurator` in this manner allows the application control over when Log4j is initialized.
+However, should any logging be attempted before `Configurator.initialize()` is called then the default configuration will be used for those log events.
+
+[#ConfigurationFactory]
+=== [[Example]] `ConfigurationFactory`
 
-Sometimes you want to configure with a configuration file but do some
-additional programmatic configuration. A possible use case might be that
-you want to allow for a flexible configuration using XML but at the same
-time make sure there are a few configuration elements that are always
-present that can't be removed.
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`] interface, which is mainly used by xref:manual/configuration.adoc#automatic-configuration[the configuration file mechanism] to load a link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`], can be leveraged to inject a custom `Configuration`.
+You need to
 
-The easiest way to achieve this is to extend one of the standard
-`Configuration` classes (`XMLConfiguration`, `JSONConfiguration`) and then
-create a new `ConfigurationFactory` for the extended class. After the
-standard configuration completes the custom configuration can be added
-to it.
+* xref:manual/configuration.adoc#ConfigurationFactory[Create a custom `ConfigurationFactory` plugin]
+* Assign it a higher priority (i.e., higher `@Order` value)
+* Support all configuration file types (i.e. return `*` from `getSupportedTypes()`)
 
-The example below shows how to extend `XMLConfiguration` to manually add
-an `Appender` and a `LoggerConfig` to the configuration.
+Consider the example below:
 
+.Snippet from an example {antora-examples-url}/manual/customconfig/ExampleConfigurationFactory.java[`ExampleConfigurationFactory.java`]
 [source,java]
 ----
-@Namespace("ConfigurationFactory")
-@Plugin("MyXMLConfigurationFactory")
-@Order(10)
-public class MyXMLConfigurationFactory extends ConfigurationFactory {
-
-    /**
-     * Valid file extensions for XML files.
-     */
-    public static final String[] SUFFIXES = new String[] {".xml", "*"};
-
-    /**
-     * Return the Configuration.
-     * @param source The InputSource.
-     * @return The Configuration.
-     */
-    public Configuration getConfiguration(InputSource source) {
-        return new MyXMLConfiguration(source, configFile);
-    }
-
-    /**
-     * Returns the file suffixes for XML files.
-     * @return An array of File extensions.
-     */
-    public String[] getSupportedTypes() {
-        return SUFFIXES;
-    }
-}
-
-public class MyXMLConfiguration extends XMLConfiguration {
-    public MyXMLConfiguration(final ConfigurationFactory.ConfigurationSource configSource) {
-      super(configSource);
-    }
-
-    @Override
-    protected void doConfigure() {
-        super.doConfigure();
-        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-        final Layout layout = PatternLayout.createDefaultLayout(config);
-        final Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
-              "false", "false", "4000", layout, null, "false", null, config);
-        appender.start();
-        addAppender(appender);
-        LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
-              "true", refs, null, config, null );
-        loggerConfig.addAppender(appender, null, null);
-        addLogger("org.apache.logging.log4j", loggerConfig);
-    }
-}
+include::example$manual/customconfig/ExampleConfigurationFactory.java[tag=class]
 ----
+<1> `getConfiguration(LoggerContext, ConfigurationSource)` is only called if `ConfigurationSource` is not null.
+This is possible if the `Configuration` is provided programmatically.
+Hence, you are encouraged to implement `getConfiguration(LoggerContext, String, URI)` overload too.
 
-[#AddingToCurrent]
-== Programmatically Modifying the Current Configuration after Initialization
+[#guides]
+== How-to guides
 
-Applications sometimes have the need to customize logging separate from
-the actual configuration. Log4j allows this although it suffers from a
-few limitations:
+In this section we will share guides on programmatically configuring Log4j Core for certain use cases.
 
-1.  If the configuration file is changed the configuration will be
-reloaded and the manual changes will be lost.
-2.  Modification to the running configuration requires that all the
-methods being called (addAppender and addLogger) be synchronized.
+[#load-config-file]
+=== Loading a configuration file
 
-As such, the recommended approach for customizing a configuration is to
-extend one of the standard Configuration classes, override the setup
-method to first do super.setup() and then add the custom Appenders,
-Filters and LoggerConfigs to the configuration before it is registered
-for use.
+<<ConfigurationFactory>> provides the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html#getInstance()[`getInstance()`] method returning a meta-`ConfigurationFactory` that combines the behaviour of all available ``ConfigurationFactory`` implementations, including xref:manual/configuration.adoc#configuration-factories[the predefined ones]; `XmlConfigurationFactory`, `JsonConfigurationFactory`, etc.
+You can use this `getInstance()` method to load a configuration file programmatically, granted that the input file format is supported by at least one of the available `ConfigurationFactory` plugins:
 
-The following example adds an Appender and a new LoggerConfig using that
-Appender to the current configuration.
-
-//TODO: update code example below with new plugin API
+.Snippet from an example {antora-examples-url}/manual/customconfig/Usage.java[`Usage.java`]
 [source,java]
 ----
-        final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
-        final Configuration config = ctx.getConfiguration();
-        Layout layout = PatternLayout.createDefaultLayout(config);
-        Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
-            "false", "false", "4000", layout, null, "false", null, config);
-        appender.start();
-        config.addAppender(appender);
-        AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
-        AppenderRef[] refs = new AppenderRef[] {ref};
-        LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
-            "true", refs, null, config, null );
-        loggerConfig.addAppender(appender, null, null);
-        config.addLogger("org.apache.logging.log4j", loggerConfig);
-        ctx.updateLoggers();
-}
+include::example$manual/customconfig/Usage.java[tag=loadConfigurationFile,indent=0]
 ----
+<1> Passing the `LoggerContext` argument as null, since this is the first time we are instantiating this `Configuration`, and it is not associated with a `LoggerContext` yet
+<2> Passing the configuration name argument as null, since it is not used when the configuration source location is provided
+<3> URI pointing to the configuration file; `file://path/to/log4j2.xml`, `classpath:log4j2.xml`, etc.
 
-[#AppendingToWritersAndOutputStreams]
-== Appending Log Events to Writers and OutputStreams Programmatically
+[#CompositeConfiguration]
+=== Combining multiple configurations
 
-Log4j 2.5 provides facilities to append log events to Writers and
-OutputStreams. For example, this provides simple integration for JDBC
-Driver implementors that use Log4j internally and still want to support
-the JDBC APIs `CommonDataSource.setLogWriter(PrintWriter)`,
-`java.sql.DriverManager.setLogWriter(PrintWriter)`, and
-`java.sql.DriverManager.setLogStream(PrintStream)`.
+include::partial$manual/composite-configuration.adoc[tag=intro]
 
-Given any `Writer`, like a `PrintWriter`, you tell Log4j to append
-events to that writer by creating a `WriterAppender` and updating the
-Log4j configuration:
+You can programmatically combine multiple configurations into a single one using link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.html[`CompositeConfiguration`]:
 
+.Snippet from an example {antora-examples-url}/manual/customconfig/Usage.java[`Usage.java`]
 [source,java]
 ----
-void addAppender(final Writer writer, final String writerName) {
-    final LoggerContext context = LoggerContext.getContext(false);
-    final Configuration config = context.getConfiguration();
-    final PatternLayout layout = PatternLayout.createDefaultLayout(config);
-    final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true);
-    appender.start();
-    config.addAppender(appender);
-    updateLoggers(appender, config);
-}
-
-private void updateLoggers(final Appender appender, final Configuration config) {
-    final Level level = null;
-    final Filter filter = null;
-    for (final LoggerConfig loggerConfig : config.getLoggers().values()) {
-        loggerConfig.addAppender(appender, level, filter);
-    }
-    config.getRootLogger().addAppender(appender, level, filter);
-}
+include::example$manual/customconfig/Usage.java[tag=combineConfigurations,indent=0]
 ----
+<1> Loading a common, and an application-specific configuration from file
+<2> Casting them to `AbstractConfiguration`, the type required by `CompositeConfiguration`
+<3> Programmatically creating an uninitialized configuration.
+Note that no casting is needed.
+<4> Creating a `CompositeConfiguration` using all three configurations created.
+Note that passed configuration order matters!
+
+.How does `CompositeConfiguration` work?
+[%collapsible]
+====
+include::partial$manual/composite-configuration.adoc[tag=how]
+====
 
-You can achieve the same effect with an `OutputStream`, like a
-`PrintStream`:
+[#Hybrid]
+=== [[AddingToCurrent]] [[AppendingToWritersAndOutputStreams]] Modifying configuration components
+
+[WARNING]
+====
+*We strongly advise against programmatically modifying components of a configuration!*
+This section will explain what it is, and why you should avoid it.
+====
+
+It is unfortunately common that users modify components (appenders, filters, etc.) of a configuration programmatically as follows:
 
 [source,java]
 ----
-void addAppender(final OutputStream outputStream, final String outputStreamName) {
-    final LoggerContext context = LoggerContext.getContext(false);
-    final Configuration config = context.getConfiguration();
-    final PatternLayout layout = PatternLayout.createDefaultLayout(config);
-    final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
-    appender.start();
-    config.addAppender(appender);
-    updateLoggers(appender, config);
-}
+LoggerContext context = LoggerContext.getContext(false);
+Configuration config = context.getConfiguration();
+PatternLayout layout = PatternLayout.createDefaultLayout(config);
+Appender appender = createCustomAppender();
+appender.start();
+config.addAppender(appender);
+updateLoggers(appender, config);
 ----
 
-The difference is the use of `OutputStreamAppender` instead of
-`WriterAppender`.
+This approach is prone several problems:
+
+* Your code relies on Log4j Core internals which don't have any backward compatibility guarantees.
+You not only risk breaking your build at a minor Log4j Core version upgrade, but also make the life of Log4j maintainers trying to evolve the project extremely difficult.
+* You move out from the safety zone, where Log4j Core takes care of components' life cycle (initialization, reconfiguration, etc.), and step into a minefield seriously undermining the reliability of your logging setup.
+
+If you happen to have code programmatically modifying components of a configuration, we advise you to migrate to other declarative approaches shared in this page.
+In case of need, feel free to ask for help in {logging-services-url}/support.html#discussions-user[user support channels].
diff --git a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc b/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
index fada282064..67748f824b 100644
--- a/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/customloglevels.adoc
@@ -56,7 +56,7 @@ Log4j contains following predefined levels:
 ====
 The `OFF` and `ALL` levels are special: they should not be used to fish-tag log events.
 
-Log4j implementations, such as Log4j Core, can use `OFF` in their configuration files to disable all log statements and `ALL` to enabled them all.
+Log4j API implementations, such as Log4j Core, can use `OFF` in their configuration files to disable all log statements and `ALL` to enabled them all.
 ====
 
 A level is composed of a case-sensitive name and a *priority* (of type `int`), which is used to define an order while comparing two.
diff --git a/src/site/antora/modules/ROOT/pages/manual/extending.adoc b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
index 317a6c3565..4b7716fa9b 100644
--- a/src/site/antora/modules/ROOT/pages/manual/extending.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
@@ -14,491 +14,141 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
-= Extending Log4j
 
-Log4j provides numerous ways that it can be manipulated and extended.
-This section includes an overview of the various ways that are directly
-supported by the Log4j 3 implementation.
+= Extending
+
+Log4j provides numerous extension points to adapt it for custom needs.
+Several of such extension points are covered in the page of the associated component:
+
+* Log4j API
+** xref:manual/customloglevels.adoc[Extending levels]
+** xref:manual/markers.adoc[Extending markers]
+** xref:manual/messages.adoc#extending[Extending messages]
+** xref:manual/thread-context.adoc#extending[Extending thread context]
+* Log4j Core
+** xref:manual/appenders.adoc#extending[Extending appenders]
+** xref:manual/filters.adoc#extending[Extending filters]
+** xref:manual/layouts.adoc#extending[Extending layouts]
+*** xref:manual/json-template-layout.adoc#extending[Extending JSON Template Layout]
+*** xref:manual/pattern-layout.adoc#extending[Extending Pattern Layout]
+** xref:manual/lookups.adoc#extending[Extending lookups]
+
+This section guides you on the rest of the Log4j extension points.
+
+[#mechanisms]
+== Extension mechanisms
+
+Log4j allows extensions primarily using following mechanisms:
+
+[#Custom_Plugins]
+=== Plugins
+
+include::partial$manual/plugin-preliminaries.adoc[]
+
+[#service-loader]
+=== ``ServiceLoader``s
+
+https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/ServiceLoader.html[`ServiceLoader`] is a simple service-provider loading facility baked into the Java platform itself.
+Log4j uses ``ServiceLoader``s for extending places where
+
+* The service needs to be implementation agnostic.
+As a result, <<Custom_Plugins,the Log4j plugin system>> cannot be used, since it is provided by the logging implementation, i.e., Log4j Core.
+For instance, this is why xref:manual/thread-context.adoc#extending[extending Thread Context], which is a Log4j API component, works using ``ServiceLoader``s.
+
+* The service needs to be loaded before <<Custom_Plugins,the Log4j plugin system>>.
+For instance, this is why <<Provider,extending `Provider`>> works using ``ServiceLoader``s.
+
+Refer to https://docs.oracle.com/javase/{java-target-version}/docs/api/java/util/ServiceLoader.html[the `ServiceLoader` documentation] for details.
+
+[#system-properties]
+=== System properties
+
+Log4j uses system properties to determine the fully-qualified class name (FQCN) to load for extending a certain functionality.
+For instance, <<MessageFactory, extending `MessageFactory2`>> works using system properties.
+
+[WARNING]
+====
+Loading a class using _only_ its FQCN can result in unexpected behaviour when there are multiple class loaders.
+====
+
+[#points]
+== Extension points
+
+In this section we will guide you on certain Log4j extension points that are not covered elsewhere.
+
+[#Provider]
+=== `Provider`
+
+link:../javadoc/log4j-api/org/apache/logging/log4j/spi/Provider.html[`Provider`] is the anchor contract binding Log4j API to an implementation.
+For instance, it has been implemented by Log4j Core, Log4j-to-JUL bridge, and Log4j-to-SLF4J bridge modules.
+
+Under the hood, link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html[`LogManager`] locates a `Provider` implementation using <<service-loader,the `ServiceLoader` mechanism>>, and delegates invocations to it.
+Hence, you can extend it by providing a `org.apache.logging.log4j.spi.Provider` implementation in the form of a `ServiceLoader`.
+
+Having multiple ``Provider``s in the classpath is strongly discouraged.
+Yet when this happens, you can use xref:manual/systemproperties.adoc#log4j2.provider[the `log4j2.provider` property] to explicitly select one.
 
 [#LoggerContextFactory]
-== LoggerContextFactory
-
-The `LoggerContextFactory` binds the Log4j API to its implementation.
-The Log4j `LogManager` locates a `LoggerContextFactory` by using
-`java.util.ServiceLoader` to locate all instances of
-`org.apache.logging.log4j.spi.Provider`. Each implementation must
-provide a class that extends `org.apache.logging.log4j.spi.Provider` and
-should have a no-arg constructor that delegates to Provider's
-constructor passing the Priority, the API versions it is compatible
-with, and the class that implements
-`org.apache.logging.log4j.spi.LoggerContextFactory`. Log4j will compare
-the current API version and if it is compatible the implementation 
-will be added to the list of providers. The API version in
-`org.apache.logging.log4j.LogManager` is only changed when a feature is
-added to the API that implementations need to be aware of. If more than
-one valid implementation is located the value for the Priority will be
-used to identify the factory with the highest priority. Finally, the
-class that implements
-`org.apache.logging.log4j.spi.LoggerContextFactory` will be instantiated
-and bound to the LogManager. In Log4j 2 this is provided by
-`Log4jContextFactory`.
-
-Applications may change the LoggerContextFactory that will be used by
-
-1.  Create a binding to the logging implementation.
-..  Implement a new link:../javadoc/log4j-core/org/apache/logging/log4j/core/impl/Log4jContextFactory.html[`LoggerContextFactory`].
-..  Implement a class that extends
-link:../javadoc/log4j-api/org/apache/logging/log4j/spi/Provider.html[`org.apache.logging.log4j.spi.Provider`]
-with a no-arg constructor that calls super-class's constructor with the
-Priority, the API version(s), `LoggerContextFactory` class, and
-optionally, a
-link:../javadoc/log4j-api/org/apache/logging/log4j/spi/ThreadContextMap.html[`ThreadContextMap`]
-implementation class.
-..  Create a `META-INF/services/org.apache.logging.spi.Provider` file
-that contains the name of the class that implements
-`org.apache.logging.spi.Provider`.
-2.  Setting the system property "log4j2.loggerContextFactory" to the name
-of the `LoggerContextFactory` class to use.
-3.  Setting the property "log4j2.loggerContextFactory" in a properties
-file named "log4j2.LogManager.properties" to the name of the
-LoggerContextFactory class to use. The properties file must be on the
-classpath.
+=== `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#LoggerContext[`LoggerContext`]s.
+If you are using Log4j Core, you can use <<ContextSelector>>s to influence the way its `LoggerContextFactory` implementation works.
+If you are creating a new Log4j API implementation, you should <<Provider,provide a custom `Provider`>> to introduce your custom `LoggerContextFactory` implementation.
 
 [#ContextSelector]
-== ContextSelector
-
-ContextSelectors are called by the
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/impl/Log4jContextFactory.html[Log4j `LoggerContext` factory]. They perform the actual work of locating or
-creating a LoggerContext, which is the anchor for Loggers and their
-configuration. ContextSelectors are free to implement any mechanism they
-desire to manage LoggerContexts. The default Log4jContextFactory checks
-for the presence of an `Injector` binding for `ContextSelector`.
-If none are defined, the System Property named "Log4jContextSelector" is checked.
-If found, the property is expected to contain the name of the Class that implements the ContextSelector to be used.
-This class is then used for creating `ContextSelector` instances.
-
-Log4j provides five ContextSelectors:
-
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/selector/BasicContextSelector.html[`BasicContextSelector`]::
-  Uses either a LoggerContext that has been stored in a ThreadLocal or a
-  common LoggerContext.
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.html[`ClassLoaderContextSelector`]::
-  Associates LoggerContexts with the ClassLoader that created the caller
-  of the getLogger(...) call. This is the default ContextSelector.
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/selector/JndiContextSelector.html[`JndiContextSelector`]::
-  Locates the LoggerContext by querying JNDI.
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/AsyncLoggerContextSelector.html[`AsyncLoggerContextSelector`]::
-  Creates a LoggerContext that ensures that all loggers are
-  AsyncLoggers.
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/osgi/BundleContextSelector.html[`BundleContextSelector`]::
-  Associates LoggerContexts with the ClassLoader of the bundle that
-  created the caller of the getLogger call. This is enabled by default
-  in OSGi environments.
+=== `ContextSelector`
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/impl/Log4jContextFactory.html[`Log4jContextFactory`], the Log4j Core implementation of <<LoggerContextFactory>>, delegates the actual work to a link:../javadoc/log4j-core/org/apache/logging/log4j/core/selector/ContextSelector.html[`ContextSelector`].
+It can be configured using xref:manual/systemproperties.adoc#log4j2.contextSelector[the `log4j2.contextSelector` property].
 
 [#ConfigurationFactory]
-== ConfigurationFactory
-
-Modifying the way in which logging can be configured is usually one of
-the areas with the most interest. The primary method for doing that is
-by implementing or extending a
-link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/ConfigurationFactory.html[`ConfigurationFactory`].
-Log4j provides two ways of adding new ConfigurationFactories. The first
-is by defining the system property named "log4j.configurationFactory" to
-the name of the class that should be searched first for a configuration.
-The second method is by defining the `ConfigurationFactory` as a `Plugin`.
-
-All the ConfigurationFactories are then processed in order. Each factory
-is called on its `getSupportedTypes()` method to determine the file
-extensions it supports. If a configuration file is located with one of
-the specified file extensions then control is passed to that
-`ConfigurationFactory` to load the configuration and create the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`] object.
-
-Most `Configuration` extend the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/AbstractConfiguration.html[`AbstractConfiguration`] class. This class expects that the subclass will process the configuration file and create
-a hierarchy of `Node` objects. Each `Node` is fairly simple in that it
-consists of the name of the node, the name/value pairs associated with
-the node, The `PluginType` of the node and a List of all of its child
-Nodes. `Configuration` will then be passed the `Node` tree and
-instantiate the configuration objects from that.
-
-[source,java]
-----
-@Namespace("ConfigurationFactory")
-@Plugin("XMLConfigurationFactory")
-@Order(5)
-public class XMLConfigurationFactory extends ConfigurationFactory {
-
-    /**
-     * Valid file extensions for XML files.
-     */
-    public static final String[] SUFFIXES = new String[] {".xml", "*"};
-
-    /**
-     * Returns the Configuration.
-     * @param loggerContext The logger context.
-     * @param source The InputSource.
-     * @return The Configuration.
-     */
-    @Override
-    public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
-        return new XmlConfiguration(loggerContext, source);
-    }
-
-    /**
-     * Returns the file suffixes for XML files.
-     * @return An array of File extensions.
-     */
-    public String[] getSupportedTypes() {
-        return SUFFIXES;
-    }
-}
-----
+=== `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#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.
+
+You can use xref:manual/systemproperties.adoc#log4j2.configurationFactory[the `log4j2.configurationFactory` property] to explicitly set a `ConfigurationFactory` to be used before any other factory implementation.
 
 [#LoggerConfig]
-== LoggerConfig
-
-`LoggerConfig` objects are where Loggers created by applications tie into
-the configuration. The Log4j implementation requires that all
-LoggerConfigs are based on the LoggerConfig class, so applications
-wishing to make changes must do so by extending the `LoggerConfig` class.
-To declare the new `LoggerConfig`, declare it as a Plugin of type "Core"
-and providing the name that applications should specify as the element
-name in the configuration. The `LoggerConfig` should also define a
-PluginFactory that will create an instance of the `LoggerConfig`.
-
-The following example shows how the root `LoggerConfig` simply extends a
-generic `LoggerConfig`.
-
-[source,java]
-----
-@Configurable(printObject = true)
-@Plugin("root")
-public static class RootLogger extends LoggerConfig {
-
-    @PluginFactory
-    public static LoggerConfig createLogger(@PluginAttribute(defaultBooleanValue = true) boolean additivity,
-                                            @PluginAttribute(defaultStringValue = "ERROR") Level level,
-                                            @PluginElement AppenderRef[] refs,
-                                            @PluginElement Filter filter) {
-        List<AppenderRef> appenderRefs = Arrays.asList(refs);
-        return new LoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs, filter, level, additivity);
-    }
-}
-----
+=== `LoggerConfig`
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/LoggerConfig.html[`LoggerConfig`] denotes the `Logger` configurations in a `Configuration`.
+A custom `LoggerConfig` needs to satisfy the following conditions:
+
+* It needs to extend from `LoggerConfig` class
+* It needs to be declared as a <<Custom_Plugins,plugin>>
+** Its plugin `category` should be set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`]
+
+For example, see `RootLogger` definition in {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java[`LoggerConfig.java`].
 
 [#LogEventFactory]
-== LogEventFactory
+=== `LogEventFactory`
 
-A LogEventFactory is used to generate LogEvents. Applications may replace the standard LogEventFactory by setting the value of the system property Log4jLogEventFactory to the name of the custom LogEventFactory class.
+Log4j Core uses link:../javadoc/log4j-core/org/apache/logging/log4j/core/impl/LogEventFactory.html[`LogEventFactory`] to create link:../javadoc/log4j-core/org/apache/logging/log4j/core/LogEvent.html[`LogEvent`]s.
+You can replace the default `LogEventFactory` implementation with a custom one of yours by using xref:manual/systemproperties.adoc#log4j2.logEventFactory[the `log4j2.logEventFactory` property].
 
-Note: When log4j is configured to have xref:manual/async.adoc#AllAsync[all
-loggers asynchronous], log events are pre-allocated in a ring buffer and
-the `LogEventFactory` is not used.
+[NOTE]
+====
+xref:manual/async.adoc[] discard `LogEventFactory` and any configuration related with it.
+====
 
 [#MessageFactory]
-== MessageFactory
-
-A `MessageFactory` is used to generate `Message` objects. Applications may
-replace the standard `ReusableMessageFactory` by setting the value of the
-system property `log4j2.messageFactory` to the name of the custom
-`MessageFactory` class.
-
-Flow messages for the `Logger.entry()` and `Logger.exit()` methods have
-a separate `FlowMessageFactory`. Applications may replace the
-`DefaultFlowMessageFactory` by setting the value of the system property
-`log4j2.flowMessageFactory` to the name of the custom `FlowMessageFactory`
-class.
-
-[#Lookups]
-== Lookups
-
-Lookups are the means in which parameter substitution is performed.
-During Configuration initialization an "Interpolator" is created that
-locates all the Lookups and registers them for use when a variable needs
-to be resolved. The interpolator matches the "prefix" portion of the
-variable name to a registered Lookup and passes control to it to resolve
-the variable.
-
-A Lookup must be declared using a `@Plugin @Lookup` annotation. The `value` specified on the `@Plugin` annotation will be used to
-match the prefix. The example below shows a Lookup that will return
-the value of a System Property.
-
-The provided Lookups are documented here: xref:manual/lookups.adoc[Lookups]
-
-[source,java]
-----
-@Lookup
-@Plugin("sys")
-public class SystemPropertiesLookup implements StrLookup {
-
-    /**
-     * Lookup the value for the key.
-     * @param key  the key to be looked up, may be null
-     * @return The value for the key.
-     */
-    public String lookup(String key) {
-        return System.getProperty(key);
-    }
-
-    /**
-     * Lookup the value for the key using the data in the LogEvent.
-     * @param event The current LogEvent.
-     * @param key  the key to be looked up, may be null
-     * @return The value associated with the key.
-     */
-    public String lookup(LogEvent event, String key) {
-        return System.getProperty(key);
-    }
-}
-----
-
-[#Filters]
-== Filters
-
-As might be expected, Filters are used to reject or accept log
-events as they pass through the logging system. A Filter is declared
-using a `@Configurable` annotation with an `elementType` of "filter".
-The `value` attribute on the `@Plugin` annotation is used to specify the name
-of the element users should use to enable the Filter. Specifying the
-`printObject` attribute with a value of "true" indicates that a call to
-`toString` will format the arguments to the filter as the configuration is
-being processed. The Filter must also specify a `@PluginFactory` method
-or `@PluginFactoryBuilder` builder class and method
-that will be called to create the Filter.
-
-The example below shows a Filter used to reject LogEvents based upon
-their logging level. Notice the typical pattern where all the filter
-methods resolve to a single filter method.
-
-[source,java]
-----
-@Plugin(name = "ThresholdFilter", category = "Core", elementType = "filter", printObject = true)
-public final class ThresholdFilter extends AbstractFilter {
-
-    private final Level level;
-
-    private ThresholdFilter(Level level, Result onMatch, Result onMismatch) {
-        super(onMatch, onMismatch);
-        this.level = level;
-    }
-
-    public Result filter(Logger logger, Level level, Marker marker, String msg, Object[] params) {
-        return filter(level);
-    }
-
-    public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
-        return filter(level);
-    }
-
-    public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
-        return filter(level);
-    }
-
-    @Override
-    public Result filter(LogEvent event) {
-        return filter(event.getLevel());
-    }
-
-    private Result filter(Level level) {
-        return level.isAtLeastAsSpecificAs(this.level) ? onMatch : onMismatch;
-    }
-
-    @Override
-    public String toString() {
-        return level.toString();
-    }
-
-    /**
-     * Create a ThresholdFilter.
-     * @param level The log Level.
-     * @param onMatch The action to take on a match.
-     * @param onMismatch The action to take on a mismatch.
-     * @return The created ThresholdFilter.
-     */
-    @PluginFactory
-    public static ThresholdFilter createFilter(@PluginAttribute(defaultStringValue = "ERROR") Level level,
-                                               @PluginAttribute(defaultStringValue = "NEUTRAL") Result onMatch,
-                                               @PluginAttribute(defaultStringValue = "DENY") Result onMismatch) {
-        return new ThresholdFilter(level, onMatch, onMismatch);
-    }
-}
-----
-
-[#Appenders]
-== Appenders
-
-Appenders are passed an event, (usually) invoke a Layout to format the
-event, and then "publish" the event in whatever manner is desired.
-Appenders are declared as `@Configurable` with an
-`elementType` of "appender". The `value` attribute on the `@Plugin` annotation
-specifies the name of the element users must provide in their
-configuration to use the Appender. Appenders should specify `printObject`
-as "true" if the toString method renders the values of the attributes
-passed to the Appender.
-
-Appenders must also declare a `@PluginFactory` method that returns an instance
-of the appender or a builder class used to create the appender. The example below shows
-an Appender named "Stub" that can be used as an initial template.
-
-Most Appenders use Managers. A manager actually "owns" the resources,
-such as an `OutputStream` or socket. When a reconfiguration occurs a new
-Appender will be created. However, if nothing significant in the
-previous Manager has changed, the new Appender will simply reference it
-instead of creating a new one. This insures that events are not lost
-while a reconfiguration is taking place without requiring that logging
-pause while the reconfiguration takes place.
-
-[source,java]
-----
-@Plugin(name = "Stub", category = "Core", elementType = "appender", printObject = true)
-public final class StubAppender extends AbstractOutputStreamAppender<StubManager> {
-
-    private StubAppender(String name,
-                         Layout<?> layout,
-                         Filter filter,
-                         boolean ignoreExceptions,
-                         StubManager  manager) {
-        super(name, layout, filter, ignoreExceptions, true, manager);
-    }
-
-    @PluginFactory
-    public static StubAppender createAppender(@PluginAttribute @Required(message = "No name provided for StubAppender") String name,
-                                              @PluginAttribute boolean ignoreExceptions,
-                                              @PluginElement Layout layout,
-                                              @PluginElement Filter filter) {
-
-        StubManager manager = StubManager.getStubManager(name);
-        if (manager == null) {
-            return null;
-        }
-        if (layout == null) {
-            layout = PatternLayout.createDefaultLayout();
-        }
-        return new StubAppender(name, layout, filter, ignoreExceptions, manager);
-    }
-}
-----
-
-[#Plugin_Builders]
-== Plugin Builders
-
-Some plugins take a lot of optional configuration options. When a plugin
-takes many options, it is more maintainable to use a builder class
-rather than a factory method (see _Item 2: Consider a builder when faced
-with many constructor parameters_ in _Effective Java_ by Joshua Bloch).
-There are some other advantages to using an annotated builder class over
-an annotated factory method:
-
-* Attribute names don't need to be specified if they match the field name or the parameter name.
-* Default values can be specified in code rather than through an
-annotation (also allowing a runtime-calculated default value which isn't
-allowed in annotations).
-* Adding new optional parameters doesn't require existing programmatic
-configuration to be refactored.
-* Easier to write unit tests using builders rather than factory methods
-with optional parameters.
-* Default values are specified via code rather than relying on
-reflection and injection, so they work programmatically as well as in a
-configuration file.
-
-Here is an example of a plugin factory from `ListAppender`:
-
-[source,java]
-----
-@PluginFactory
-public static ListAppender createAppender(
-        @PluginAttribute("name") @Required(message = "No name provided for ListAppender") final String name,
-        @PluginAttribute("entryPerNewLine") final boolean newLine,
-        @PluginAttribute("raw") final boolean raw,
-        @PluginElement("Layout") final Layout<? extends Serializable> layout,
-        @PluginElement("Filter") final Filter filter) {
-    return new ListAppender(name, filter, layout, newLine, raw);
-}
-----
-
-Here is that same factory using a builder pattern instead:
-
-[source,java]
-----
-@PluginBuilderFactory
-public static Builder newBuilder() {
-    return new Builder();
-}
-
-public static class Builder implements org.apache.logging.log4j.core.util.Builder<ListAppender> {
-
-    @PluginBuilderAttribute
-    @Required(message = "No name provided for ListAppender")
-    private String name;
-
-    @PluginBuilderAttribute
-    private boolean entryPerNewLine;
-
-    @PluginBuilderAttribute
-    private boolean raw;
-
-    @PluginElement("Layout")
-    private Layout<? extends Serializable> layout;
-
-    @PluginElement("Filter")
-    private Filter filter;
-
-    public Builder setName(final String name) {
-        this.name = name;
-        return this;
-    }
-
-    public Builder setEntryPerNewLine(final boolean entryPerNewLine) {
-        this.entryPerNewLine = entryPerNewLine;
-        return this;
-    }
-
-    public Builder setRaw(final boolean raw) {
-        this.raw = raw;
-        return this;
-    }
-
-    public Builder setLayout(final Layout<? extends Serializable> layout) {
-        this.layout = layout;
-        return this;
-    }
-
-    public Builder setFilter(final Filter filter) {
-        this.filter = filter;
-        return this;
-    }
-
-    @Override
-    public ListAppender build() {
-        return new ListAppender(name, filter, layout, entryPerNewLine, raw);
-    }
-}
-----
-
-The only difference in annotations is using `@PluginBuilderAttribute` instead of `@PluginAttribute`
-so that default values and reflection can be used instead of specifying them in the annotation.
-Either annotation can be used in a builder, but the former is better suited for field injection
-while the latter is better suited for parameter injection. Otherwise, the same annotations
-(`@PluginConfiguration`, `@PluginElement`, `@PluginNode`, and `@PluginValue`) are all supported on fields.
-Note that a factory method is still required to supply a builder, and this factory method
-should be annotated with `@PluginBuilderFactory`.
-
-When plugins are being constructed after a configuration has been
-parsed, a plugin builder will be used if available, otherwise a plugin
-factory method will be used as a fallback. If a plugin contains neither
-factory, then it cannot be used from a configuration file (it can still
-be used programmatically of course).
-
-Here is an example of using a plugin factory versus a plugin builder
-programmatically:
-
-[source,java]
-----
-ListAppender list1 = ListAppender.createAppender("List1", true, false, null, null);
-ListAppender list2 = ListAppender.newBuilder().setName("List1").setEntryPerNewLine(true).build();
-----
+=== `MessageFactory2`
 
-[#Custom_Plugins]
-== Custom Plugins
+Log4j Core uses link:../javadoc/log4j-api/org/apache/logging/log4j/message/MessageFactory2.html[`MessageFactory2`] to create link:../javadoc/log4j-api/org/apache/logging/log4j/message/Message.html[`Message`]s.
+You can replace the default `MessageFactory2` implementation with a custom one of yours by using xref:manual/systemproperties.adoc#log4j2.messageFactory[the `log4j2.messageFactory` property].
+
+In the case of xref:manual/flowtracing.adoc[], Log4j Core uses link:../javadoc/log4j-api/org/apache/logging/log4j/message/FlowMessageFactory.html[`FlowMessageFactory`].
+You can replace the default `FlowMessageFactory` implementation with a custom one of yours by using xref:manual/systemproperties.adoc#log4j2.flowMessageFactory[the `log4j2.flowMessageFactory` property].
+
+[IMPORTANT]
+====
+Message factory implementations are expected to interpret formatting patterns containing placeholders denoted with `{}`.
+For instance, the default message factory chooses between a xref:manual/messages.adoc#SimpleMessage[`SimpleMessage`] and a xref:manual/messages.adoc#ParameterizedMessage[`ParameterizedMessage`] depending on the presence of placeholders in the formatting pattern.
 
-// TODO
-See the xref:manual/plugins.adoc[Plugins] section of the manual.
+If you want to change the placeholder style (e.g., switching from `{}` to `%s`), you should *not* replace the default message factory.
+Because this will break the existing Log4j API calls using the standard placeholder style.
+Instead, you can use link:../javadoc/log4j-api/org/apache/logging/log4j/LogManager.html[`LogManager`] methods accepting a message factory to create ``Logger``s with your custom message factory implementations.
+====
diff --git a/src/site/antora/modules/ROOT/pages/manual/filters.adoc b/src/site/antora/modules/ROOT/pages/manual/filters.adoc
index 031192e3a2..ad8eaeff12 100644
--- a/src/site/antora/modules/ROOT/pages/manual/filters.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/filters.adoc
@@ -14,6 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 ////
+
 [id=filters]
 = Filters
 
@@ -89,8 +90,14 @@ Users migrating from Log4j 1 often replace the `threshold` property of a Log4j 1
 Using the `level` property of appender references will give a better performance.
 ====
 
+[#collection]
+== Collection
+
+Log4j bundles several predefined filters to assist in several common deployment use cases.
+Following sections explain all these in detail.
+
 [#BurstFilter]
-== BurstFilter
+=== BurstFilter
 
 The BurstFilter provides a mechanism to control the rate at which LogEvents are processed by silently discarding events after the maximum limit has been reached.
 
@@ -152,7 +159,7 @@ A configuration containing the BurstFilter might look like:
 ----
 
 [#CompositeFilter]
-== CompositeFilter
+=== CompositeFilter
 
 The CompositeFilter provides a way to specify more than one filter.
 It is added to the configuration as a filter element and contains other filters to be evaluated.
@@ -198,7 +205,7 @@ A configuration containing the CompositeFilter might look like:
 ----
 
 [#DynamicThresholdFilter]
-== DynamicThresholdFilter
+=== DynamicThresholdFilter
 
 The DynamicThresholdFilter allows filtering by log level based on specific attributes.
 For example, if the user's loginId is being captured in the ThreadContext Map then it is possible to enable debug logging for only that user.
@@ -266,7 +273,7 @@ Here is a sample configuration containing the DynamicThresholdFilter:
 ----
 
 [#LevelRangeFilter]
-== LevelRangeFilter
+=== LevelRangeFilter
 
 `LevelRangeFilter` allows filtering against a level range, where levels get compared by their associated integral values; `OFF` has an integral value of 0, `FATAL` 100, `ERROR` 200, and so on.
 
@@ -315,7 +322,7 @@ The filter will return `onMismatch` result (i.e., `DENY`, the default) for log e
 ----
 
 [#MapFilter]
-== MapFilter
+=== MapFilter
 
 The MapFilter allows filtering against data elements that are in a MapMessage.
 
@@ -435,7 +442,7 @@ This third sample configuration will exhibit the same behavior as the preceding
 ----
 
 [#MarkerFilter]
-== MarkerFilter
+=== MarkerFilter
 
 The MarkerFilter compares the configured Marker value against the Marker that is included in the LogEvent.
 A match occurs when the Marker name matches either the Log Event's Marker or one of its parents.
@@ -485,7 +492,7 @@ A sample configuration that only allows the event to be written by the appender
 ----
 
 [#MutableThreadContextMapFilter]
-== MutableThreadContextMapFilter
+=== MutableThreadContextMapFilter
 
 The MutableThreadContextMapFilter or MutableContextMapFilter allows filtering against data elements that are in the current context.
 By default, this is the ThreadContext Map.
@@ -559,7 +566,7 @@ The configuration file supplied to the filter should look similar to:
 ----
 
 [#NoMarkerFilter]
-== NoMarkerFilter
+=== NoMarkerFilter
 
 The NoMarkerFilter checks that there is no marker included in the LogEvent.
 A match occurs when there is no marker in the Log Event.
@@ -605,7 +612,7 @@ A sample configuration that only allows the event to be written by the appender
 ----
 
 [#RegexFilter]
-== RegexFilter
+=== RegexFilter
 
 The RegexFilter allows the formatted or unformatted message to be compared against a regular expression.
 
@@ -775,7 +782,7 @@ xref:manual/appenders.adoc#ScriptCondition[ScriptCondition] for an example of ho
 ----
 
 [#StructuredDataFilter]
-== StructuredDataFilter
+=== StructuredDataFilter
 
 The StructuredDataFilter is a MapFilter that also allows filtering on the event id, type and message.
 
@@ -840,7 +847,7 @@ As in this configuration, the StructuredDataFilter can be used to log particular
 ----
 
 [#ThreadContextMapFilter]
-== ThreadContextMapFilter
+=== ThreadContextMapFilter
 
 The ThreadContextMapFilter or ContextMapFilter allows filtering against data elements that are in the current context.
 By default, this is the ThreadContext Map.
@@ -932,7 +939,7 @@ The ContextMapFilter can also be applied to a logger for filtering:
 ----
 
 [#ThresholdFilter]
-== ThresholdFilter
+=== ThresholdFilter
 
 This filter returns the onMatch result if the level in the LogEvent is the same or more specific than the configured level and the `onMismatch`
 value otherwise.
@@ -984,7 +991,7 @@ A sample configuration that only allows the event to be written by the appender
 ----
 
 [#TimeFilter]
-== TimeFilter
+=== TimeFilter
 
 The time filter can be used to restrict the filter to only a certain portion of the day.
 
@@ -1041,3 +1048,35 @@ A sample configuration that only allows the event to be written by the appender
   </Loggers>
 </Configuration>
 ----
+
+[#extending]
+== Extending
+
+Filters are xref:manual/plugins.adoc[plugins] implementing link:../javadoc/log4j-core/org/apache/logging/log4j/core/Filter.html[the `Filter` interface].
+This section will guide you on how to create custom ones.
+
+[NOTE]
+====
+While <<collection,the predefined filter collection>> should address most common use cases, you might find yourself needing to implement a custom one.
+If this is the case, we really appreciate it if you can *share your use case in a {logging-services-url}/support.html[user support channel]*.
+====
+
+[#extending-plugins]
+=== Plugin preliminaries
+
+include::partial$manual/plugin-preliminaries.adoc[]
+
+[#extending-filters]
+=== Extending filters
+
+Filter are xref:manual/plugins.adoc[plugins] implementing link:../javadoc/log4j-core/org/apache/logging/log4j/core/Filter.html[the `Filter` interface].
+We recommend users to extend from link:../javadoc/log4j-core/org/apache/logging/log4j/core/filter/AbstractFilter.html[`AbstractFilter`], which provides implementation convenience.
+While annotating your filter with `@Plugin`, you need to make sure that
+
+* It has a unique `name` attribute across all available `Filter` plugins
+* The `category` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`]
+
+You can check out following files for examples:
+
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/MarkerFilter.java[`MarkerFilter.java`] – <<MarkerFilter>> matching on markers associated with the effective `LogEvent` in the context
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/RegexFilter.java[`RegexFilter.java`] – <<RegexFilter>> matching on the message associated with the effective `LogEvent` in the context
diff --git a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
index 0b7d656a8d..87feb17eaf 100644
--- a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
@@ -57,7 +57,7 @@ If not for yours, keep on reading.
 In order to have a garbage-free Log4j Core, you need to
 
 * <<core-properties,configure it using properties>>,
-* and employ garbage-free <<Layouts,layouts>>, <<Appenders,appenders>>, and <<Filters,filters>>.
+* and employ garbage-free <<Layouts>>, <<Appenders>>, and <<Filters>>.
 
 [#core-properties]
 === Properties
diff --git a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
index 1551802e5f..956b8823a1 100644
--- a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
@@ -1109,6 +1109,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
+* The `category` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`]
+
 You can check out following files for examples:
 
 * {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SyslogLayout.java[`SyslogLayout.java`] – simple, single-file, extending from `AbstractStringLayout`
diff --git a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
index b417b5cd9e..86fbe88923 100644
--- a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
@@ -25,8 +25,14 @@ be found in the xref:manual/configuration.adoc#PropertySubstitution[Property
 Substitution] section of the xref:manual/configuration.adoc[Configuration]
 page.
 
+[#collection]
+== Collection
+
+Log4j bundles several predefined lookups to assist in several common deployment use cases.
+Following sections explain all these in detail.
+
 [#ContextMapLookup]
-== Context Map Lookup
+=== Context Map Lookup
 
 The ContextMapLookup allows applications to store data in the Log4j
 ThreadContext Map and then retrieve the values in the Log4j
@@ -47,7 +53,7 @@ resolve the variable for each event. Note that the pattern
 ----
 
 [#DateLookup]
-== Date Lookup
+=== Date Lookup
 
 The DateLookup is somewhat unusual from the other lookups as it doesn't
 use the key to locate an item. Instead, the key can be used to specify a
@@ -67,7 +73,7 @@ be formatted as specified.
 ----
 
 [#DockerLookup]
-== Docker Lookup
+=== Docker Lookup
 
 The DockerLookup can be used to lookup attributes from the Docker container the application is running in.
 
@@ -107,7 +113,7 @@ Log4j Docker provides access to the following container attributes:
 This Lookup is subject to the requirements listed at xref:log4j-docker.adoc[Log4j Docker Support]
 
 [id=environment-lookup]
-== [[EnvironmentLookup]] Environment Lookup
+=== [[EnvironmentLookup]] Environment Lookup
 
 The EnvironmentLookup allows systems to configure environment variables,
 either in global files such as /etc/profile or in the startup scripts
@@ -136,8 +142,9 @@ when the `USER` environment variable is undefined, the default value
   </PatternLayout>
 </File>
 ----
+
 [#EventLookup]
-== Event Lookup
+=== Event Lookup
 
 The EventLookup provides access to fields within the log event from the configuration.
 
@@ -212,7 +219,7 @@ present in the log event.
 ----
 
 [#JavaLookup]
-== Java Lookup
+=== Java Lookup
 
 The JavaLookup allows Java environment information to be retrieved in
 convenient preformatted strings using the `java:` prefix.
@@ -265,7 +272,7 @@ For example:
 ----
 
 [#JndiLookup]
-== JNDI Lookup
+=== JNDI Lookup
 
 As of Log4j 2.15.1 JNDI operations require that `log4j2.enableJndi=true` be set as a system property or the
 corresponding environment variable for this lookup to function. See the
@@ -295,7 +302,7 @@ or ip address are supported along with any hosts or ip addresses listed in the
 *Java's JNDI module is not available on Android.*
 
 [#JmxRuntimeInputArgumentsLookup]
-== JVM Input Arguments Lookup (JMX)
+=== JVM Input Arguments Lookup (JMX)
 
 Maps JVM input arguments -- but not _main_ arguments -- using JMX to
 acquire the JVM arguments.
@@ -308,7 +315,7 @@ https://docs.oracle.com/javase/{java-target-version}/docs/api/java/lang/manageme
 *Java's JMX module is not available on Android or on Google App Engine.*
 
 [#KubernetesLookup]
-== Kubernetes Lookup
+=== Kubernetes Lookup
 
 For retrieving attributes using Fabric8's Kubernetes Client, see their https://github.com/fabric8io/kubernetes-client/blob/main/doc/KubernetesLog4j.md[Kubernetes Log4j Lookup].
 
@@ -333,7 +340,7 @@ relative to the log4j configuration file.
 ----
 
 [#LowerLookup]
-== Lower Lookup
+=== Lower Lookup
 
 The LowerLookup converts the passed in argument to lower case. Presumably the value will be the
 result of a nested lookup.
@@ -348,7 +355,7 @@ result of a nested lookup.
 ----
 
 [#AppMainArgsLookup]
-== Main Arguments Lookup (Application)
+=== Main Arguments Lookup (Application)
 
 This lookup requires that you manually provide the main arguments of the
 application to Log4j:
@@ -378,9 +385,10 @@ key must be followed by a backslash as an escape character as in `${main:\--file
 
 For example, suppose the static void main String[] arguments are:
 
-....
+[source,text]
+----
 --file foo.txt --verbose -x bar
-....
+----
 
 Then the following substitutions are possible:
 
@@ -428,7 +436,7 @@ Example usage:
 ----
 
 [#MapLookup]
-== Map Lookup
+=== Map Lookup
 
 The MapLookup serves several purposes.
 
@@ -470,7 +478,7 @@ page for information on how to set the default values.
 ----
 
 [#marker-lookup]
-== Marker Lookup
+=== Marker Lookup
 
 The marker lookup allows you to use markers in interesting
 configurations like a routing appender. Consider the following YAML
@@ -539,7 +547,8 @@ You can use the notation `"${marker:name}"` and `"$${marker:name}"` to
 check for the existence of a marker where `name` is the marker name. If
 the marker exists, the expression returns the name, otherwise `null`.
 
-== Resource Bundle Lookup
+=== Resource Bundle Lookup
+
 The resource bundle lookup retrieves values from Resource Bundles (see Java documentation). The format is `${bundle:BundleName:BundleKey}`. The bundle name follows package naming conventions, for example: `${bundle:com.domain.Messages:MyKey}`.
 
 [source, xml]
@@ -551,7 +560,8 @@ The resource bundle lookup retrieves values from Resource Bundles (see Java docu
 </File>
 ----
 
-== Spring Boot Lookup
+=== Spring Boot Lookup
+
 The Spring Boot Lookup retrieves the values of Spring properties from the Spring configuration as well as values of the active and default profiles. Specifying a key of "profiles.active" will return the active profiles while a key of "profiles.default" will return the default profiles. The default and active profiles can be an array. If more than one profile is present they will be returned as a comma separated list. To retrieve a single item from the array append "[\{index}]" to the key [...]
 
 This Lookup will return null values until Spring Boot initializes application logging. The Spring Boot Lookup requires the log4j-spring-boot jar be included as a dependency.
@@ -568,7 +578,7 @@ This Lookup will return null values until Spring Boot initializes application lo
 This Lookup requires log4j-spring-cloud-config-client be included in the application.
 
 [#StructuredDataLookup]
-== Structured Data Lookup
+=== Structured Data Lookup
 
 The StructuredDataLookup is very similar to the MapLookup in that it
 will retrieve values from StructuredDataMessages. In addition to the Map
@@ -597,7 +607,7 @@ while "type" would have to be an item in the Map in a MapMessage.
 ----
 
 [id=system-properties-lookup]
-== [[SystemPropertiesLookup]] System Properties Lookup
+=== [[SystemPropertiesLookup]] System Properties Lookup
 
 As it is quite common to define values inside and outside the
 application by using System Properties, it is only natural that they
@@ -624,7 +634,7 @@ when the `logPath` system property is undefined, the default value
 ----
 
 [#UpperLookup]
-== Upper Lookup
+=== Upper Lookup
 
 The LowerLookup converts the passed in argument to upper case. Presumably the value will be the
 result of a nested lookup.
@@ -639,7 +649,7 @@ result of a nested lookup.
 ----
 
 [#WebLookup]
-== Web Lookup
+=== Web Lookup
 
 The WebLookup allows applications to retrieve variables that are
 associated with the ServletContext. In addition to being able to
@@ -699,3 +709,34 @@ located then the corresponding value will be returned.
   <File name="ApplicationLog" fileName="${web:rootDir}/app.log"/>
 </Appenders>
 ----
+
+[#extending]
+== Extending
+
+Lookups are xref:manual/plugins.adoc[plugins] implementing link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html[the `StrLookup` interface].
+This section will guide you on how to create custom ones.
+
+[NOTE]
+====
+While <<collection,the predefined lookup collection>> should address most common use cases, you might find yourself needing to implement a custom one.
+If this is the case, we really appreciate it if you can *share your use case in a {logging-services-url}/support.html[user support channel]*.
+====
+
+[#extending-plugins]
+=== Plugin preliminaries
+
+include::partial$manual/plugin-preliminaries.adoc[]
+
+[#extending-lookups]
+=== Extending lookups
+
+Lookups are xref:manual/plugins.adoc[plugins] implementing link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html[the `StrLookup` interface].
+While annotating your lookup with `@Plugin`, you need to make sure that
+
+* It has a unique `name` attribute across all available `StrLookup` plugins
+* The `category` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html#CATEGORY[`StrLookup.CATEGORY`]
+
+You can check out following files for examples:
+
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/DateLookup.java[`LowerLookup.java`] – <<LowerLookup>> lower-cases its input
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/EventLookup.java[`EventLookup.java`] – <<EventLookup>> extracts specified fields from the effective `LogEvent` in the context
diff --git a/src/site/antora/modules/ROOT/pages/manual/markers.adoc b/src/site/antora/modules/ROOT/pages/manual/markers.adoc
index 5d98dbf601..740aed4cc0 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]
@@ -157,7 +155,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:
diff --git a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index ab4216480f..5a6d655e2a 100644
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@ -1592,33 +1592,33 @@ Format modifiers to control such things as field width, padding, left, and right
 |Pattern
 |Comment
 
-|xref:#converter-logger[%c\{precision} +
-%logger\{precision}]
+|<<converter-logger,%c\{precision} +
+%logger\{precision}>>
 |
 
-|xref:#converter-date[%d +
-%date]
+|<<converter-date,%d +
+%date>>
 |Only the predefined date formats (`DEFAULT`, `ISO8601`, `UNIX`, `UNIX_MILLIS`, etc.) are garbage-free
 
-|xref:#converter-encode[%enc\{pattern} +
-%encode\{pattern}]
+|<<converter-encode,%enc\{pattern} +
+%encode\{pattern}>>
 |
 
-|xref:#converter-equals[%equals\{pattern}\{test}\{substitution} +
-%equalsIgnoreCase\{pattern}\{test}\{substitution}]
+|<<converter-equals,%equals\{pattern}\{test}\{substitution} +
+%equalsIgnoreCase\{pattern}\{test}\{substitution}>>
 |
 
 |<<converter-highlight,%highlight\{pattern}\{style}>>
 |Granted nested pattern is garbage-free
 
-|xref:#converter-map[%K\{key} +
+|<<converter-map,%K\{key} +
 %map\{key} +
-%MAP\{key}]
+%MAP\{key}>>
 |
 
-|xref:#converter-message[%m +
+|<<converter-message,%m +
 %msg +
-%message]
+%message>>
 |
 
 |<<converter-marker,%marker>>
@@ -1627,54 +1627,54 @@ Format modifiers to control such things as field width, padding, left, and right
 |<<converter-marker,%markerSimpleName>>
 |
 
-|xref:#converter-max-len[%maxLen +
-%maxLength]
+|<<converter-max-len,%maxLen +
+%maxLength>>
 |
 
 |%n
 |
 
-|xref:#converter-nano[%N +
-%nano]
+|<<converter-nano,%N +
+%nano>>
 |
 
-|xref:#converter-not-empty[%notEmpty\{pattern} +
+|<<converter-not-empty,%notEmpty\{pattern} +
 %varsNotEmpty\{pattern} +
-%variablesNotEmpty\{pattern}]
+%variablesNotEmpty\{pattern}>>
 |
 
-|xref:#converter-level[%p +
-%level]
+|<<converter-level,%p +
+%level>>
 |
 
-|xref:#converter-relative[%r +
-%relative]
+|<<converter-relative,%r +
+%relative>>
 |
 
-|xref:#converter-seq[%sn +
-%sequenceNumber]
+|<<converter-seq,%sn +
+%sequenceNumber>>
 |
 
 |<<converter-style,%style\{pattern}{ANSI style}>>
 |
 
-|xref:#converter-thread-id[%T +
+|<<converter-thread-id,%T +
 %tid +
-%threadId]
+%threadId>>
 |
 
-|xref:#converter-thread-name[%t +
+|<<converter-thread-name,%t +
 %tn +
 %thread +
-%threadName]
+%threadName>>
 |
 
 |<<converter-thread-priority,%tp>>
 |
 
-|<<converter-thread-context-map[%X{key,,key2...\>>} +
+|<<converter-thread-context-map[%X{key,,key2...\} +
 %mdc{key[,key2...\]} +
-%MDC{key[,key2...\]}]
+%MDC{key[,key2...\]}>>
 |
 
 |literal text
diff --git a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
index c793d404c4..17ce5d8e72 100644
--- a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
@@ -14,39 +14,220 @@
     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.
+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`.
+`name` matching is case-insensitive.
+
+`category` (optional)::
+A name used for grouping a set of plugins.
+`category` matching is case-sensitive.
+
+`elementType` (deprecated)::
+We don't recommend the usage of `elementType` anymore.
+Existing usages are kept for backward compatibility reasons with the legacy configuration syntax: `<appender type="ConsoleAppender"`.
+
+See {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/LowerLookup.java[`LowerLookup.java`] (a xref:manual/lookups.adoc[lookup] for lower-casing its input) for a simple example.
+
+.Click to read more on *name collision* and *overriding an existing plugin*
+[%collapsible]
+====
+The `name` attribute of plugins of a certain `category` is recommended to be distinct and this matching is case-insensitive.
+In case of a name collision, a warning will be emitted, and the plugin <<plugin-discovery,discovery order>> will determine the effective plugin.
+For example, to override the `File` plugin which is provided by the built-in xref:manual/appenders.adoc#FileAppender[File Appender], you would need to place your plugin in a JAR file in the classpath ahead of Log4j Core JAR.
+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.
+====
+
+[#core]
+== Declaring plugins represented in a configuration file
+
+If your plugin needs to be represented by an element in a configuration file (such as an xref:manual/appenders.adoc[appender], xref:manual/layouts.adoc[layout], xref:manual/api.adoc#loggers[logger], or xref:manual/filters.adoc[filter]), following requirements must be met:
+
+* The `category` attribute of the `@Plugin` annotation must be set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`] (`Core`)
+* It must have a xref:declare-plugin-factory[plugin factory]
+
+See {project-github-url}/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java[`JsonTemplateLayout.java`] for an example and notice these details:
+
+* There are two plugin declarations: `JsonTemplateLayout` and `JsonTemplateLayout.EventTemplateAdditionalField`
+* Both plugin declarations
+** Set the `category` attribute to `Node.CATEGORY`
+** Provide a `@PluginBuilderFactory`-annotated static method
+
+[#declare-plugin-factory]
+=== Declaring plugin factories
+
+A *plugin factory* is responsible for
+
+* Creating an instance of the plugin
+* Receiving values (`Configuration` instance, configuration attributes, etc.) available in the context
+
+Every plugin that needs to be represented by an element in a configuration file must declare a plugin factory using one of the following:
+
+a link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginFactory.html[`@PluginFactory`]-annotated static method::
+What is expected to be received is modelled as method arguments.
+Intended for simple plugins that receive less than a handful of values.
++
+See {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java[`CsvParameterLayout.java`] for an example on `@PluginFactory` usage.
+
+a link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginBuilderFactory.html[`@PluginBuilderFactory`]-annotated static method of return type link:../javadoc/log4j-core/src/main/java/org/apache/logging/log4j/core/util/Builder.java[`Builder<T>`]::
+What is expected to be received is modelled as fields of a builder class.
+Intended for more sophisticated wiring needs.
++
+.Click for advantages of builder class over factory method
+[%collapsible]
+====
+* Attribute names don't need to be specified, if they match the field name
+* Default values can be specified in code rather than through an annotation.
+This also allows a runtime-calculated default value, which isn't allowed in annotations.
+* Default values are specified via code rather than relying on reflection and injection, so they work programmatically as well as in a configuration file.
+* Adding new optional parameters doesn't require existing programmatic configuration to be refactored.
+* Easier to write unit tests using builders rather than factory methods with optional parameters.
+====
++
+See {project-github-url}/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java[`JsonTemplateLayout.java`] for an example on `@PluginBuilderFactory` usage.
+
+If a plugin class implements `Collection` or `Map`, then no factory method is used.
+Instead, the class is instantiated using the default constructor, and all child configuration nodes are added to the `Collection` or `Map`.
+
+[#attribute-types]
+==== Plugin factory attribute types
+
+To allow the current `Configuration` to populate the correct arguments for the `@PluginFactory`-annotated method (or fields for the builder class), every argument to the method must be annotated using one of the following attribute types.
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginAliases.html[`@PluginAliases`]::
+Identifies a list of aliases for a `@Plugin`, `@PluginAttribute`, or `@PluginBuilderAttribute`
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginAttribute.html[`@PluginAttribute`]::
+Denotes a configuration element attribute.
+The parameter must be convertible from a `String` using a `TypeConverter`.
+Most built-in types are already supported, but custom `TypeConverter` plugins may also be provided for more type support.
+Note that `PluginBuilderAttribute` can be used in builder class fields as an easier way to provide default values.
 
-In Log4j 2 a plugin is declared by adding a link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/Plugin.html[`@Plugin`] annotation to the class declaration. During initialization the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`] will invoke the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/util/PluginManager.html[`PluginManager`] to load the built-in Log4j plugins as well as any custom plug [...]
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.html[`@PluginConfiguration`]::
+The current `Configuration` object will be passed to the plugin as a parameter.
 
-1. Serialized plugin listing files on the classpath. These files 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-core` has started.
-3. **(Deprecated)** A comma-separated list of packages specified by the `log4j.plugin.packages` system property.
-4. **(Deprecated)** Packages passed to the static `PluginManager.addPackages` method (before Log4j configuration occurs).
-5. **(Deprecated)** The [packages](./configuration.html#ConfigurationSyntax) declared in your log4j2 configuration file.
+[[PluginElement]] link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginElement.html[`@PluginElement`]::
+The parameter may represent a complex object that itself has parameters that can be configured.
+This also supports injecting an array of elements.
 
-If multiple Plugins specify the same (case-insensitive) `name`, then the load order above determines which one will be used. 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  [...]
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginNode.html[`@PluginNode`]::
+The current `Node` being parsed will be passed to the plugin as a parameter.
 
-Serialized plugin listing files are generated by an annotation processor contained in the log4j-core artifact which will automatically scan your code for Log4j 2 plugins and output a metadata file in your processed classes. 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. In that case, it would be important to add another compiler pass to your build proces [...]
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginValue.html[`@PluginValue`]::
+The value of the current `Node` or its attribute named `value`.
 
-[source,xml]
+Each attribute or element annotation must include the name that must be present in the configuration in order to match the configuration item to its respective parameter.
+For plugin builders, the names of the fields will be used by default if no name is specified in the annotation.
+
+[#type-converters]
+==== Plugin factory attribute type converters
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/convert/TypeConverter.html[`TypeConverter`]s are a certain group of plugins for converting ``String``s read from configuration file elements into the types used in plugin factory attributes.
+Other plugins can already be injected via <<PluginElement,the `@PluginElement` annotation>>; now, any type supported by ``TypeConverter``s can be used in a `@PluginAttribute`-annotated factory attribute.
+
+Conversion of enum types are supported on demand and do not require custom ``TypeConverter``s.
+A large number of built-in Java classes (`int`, `long`, `BigDecimal`, etc.) are already supported; see link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/convert/TypeConverters.html[`TypeConverters`] for a more exhaustive listing.
+
+You can create custom ``TypeConverter``s as follows:
+
+* Extend from link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/convert/TypeConverter.html[the `TypeConverter` interface]
+
+* Set the `category` attribute of the `@Plugin` annotation to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/convert/TypeConverters.html#CATEGORY[`TypeConverters.CATEGORY`] (`TypeConverter`).
+Unlike other plugins, the plugin name of a `TypeConverter` is purely cosmetic.
+
+* Have a default constructor
+
+* Optionally, extend from `Comparable<TypeConverter<?>>`, which will be used for determining the order in case of multiple `TypeConverter` candidates for a certain type
+
+See {project-github-url}/log4j-core/org/apache/logging/log4j/core/config/plugins/convert/TypeConverters.java[`TypeConverters.java`] for example implementations.
+
+[#constraint-validators]
+==== Plugin factory attribute validators
+
+Plugin factory fields and parameters can be automatically validated at runtime using constraint validators inspired by https://beanvalidation.org[Bean Validation].
+The following annotations are bundled in Log4j, but custom ``ConstraintValidator`` can be created as well.
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/validation/constraints/Required.html[`@Required`]::
+This annotation validates that a value is non-empty.
+This covers a check for null as well as several other scenarios: empty `CharSequence` objects, empty arrays, empty `Collection` instances, and empty `Map` instances.
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/validation/constraints/ValidHost.html[`@ValidHost`]::
+This annotation validates that a value corresponds to a valid host name.
+This uses the same validation as https://docs.oracle.com/javase/{java-target-version}/docs/api/java/net/InetAddress.html#getByName-java.lang.String-[`InetAddress.getByName(String)`].
+
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/validation/constraints/ValidPort.html[`@ValidPort`]::
+This annotation validates that a value corresponds to a valid port number between 0 and 65535.
+
+[#plugin-registry]
+== Registering plugins
+
+Registering plugins are done by placing a *Log4j plugin descriptor* (i.e., `Log4j2Plugins.dat`) into the classpath.
+This file is generated using the link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/processor/PluginProcessor.html[`PluginProcessor`] annotation processor at compile-time.
+You need to configure your build tool as follows to employ `PluginProcessor` by the Java compiler:
+
+[tabs]
+====
+Maven::
++
+[source,xml,subs="+attributes"]
 ----
 <plugin>
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-compiler-plugin</artifactId>
-  <version>3.1</version>
+  <version>${maven-compiler-plugin.version}</version>
   <executions>
     <execution>
-      <id>log4j-plugin-processor</id>
+      <id>generate-log4j-plugin-descriptor</id>
       <goals>
         <goal>compile</goal>
       </goals>
       <phase>process-classes</phase>
       <configuration>
         <proc>only</proc>
+        <annotationProcessorPaths>
+          <!-- Include `log4j-core` providing `org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor` that generates `Log4j2Plugins.dat` -->
+          <path>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>{log4j-core-version}</version>
+          </path>
+        </annotationProcessorPaths>
         <annotationProcessors>
-          <annotationProcessor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor</annotationProcessor>
+          <!-- Process sources using `org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor` to generate `Log4j2Plugins.dat` -->
+          <processor>org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor</processor>
         </annotationProcessors>
       </configuration>
     </execution>
@@ -54,48 +235,44 @@ Serialized plugin listing files are generated by an annotation processor contain
 </plugin>
 ----
 
-[#core]
-== Core
-Core plugins are those that are directly represented by an element in a configuration file, such as an Appender, Layout, Logger or Filter. Custom plugins that conform to the rules laid out in the next paragraph may simply be referenced in the configuration, provided they are appropriate configured to be loaded by the PluginManager.
-
-Every Core plugin must declare a static method annotated with @PluginFactory or @PluginBuilderFactory. The former is used for static factory methods that provide all options as method parameters, and the latter is used to construct a new Builder<T> class whose fields are used for injecting attributes and child nodes. To allow the Configuration to pass the correct parameters to the method, every parameter to the method must be annotated as one of the following attribute types. Each attrib [...]
-
-[#attribute-types]
-=== Attribute types
-
-* PluginAttribute: The parameter must be convertible from a String using a TypeConverter. Most built-in types are already supported, but custom TypeConverter plugins may also be provided for more type support. Note that PluginBuilderAttribute can be used in builder class fields as an easier way to provide default values.
-* PluginElement: The parameter may represent a complex object that itself has parameters that can be configured. This also supports injecting an array of elements.
-* PluginConfiguration: The current Configuration object will be passed to the plugin as a parameter.
-* PluginNode: The current Node being parsed will be passed to the plugin as a parameter.
-* PluginValue: The value of the current Node or its attribute named value.
-
-[#constraint-validators]
-=== Constraint validators
+Gradle::
++
+[source,groovy,subs="+attributes"]
+----
+dependencies {
+  // Process sources using `log4j-core` providing `org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor` that generates `Log4j2Plugins.dat` -->
+  annotationProcessor('org.apache.logging.log4j:log4j-core:{log4j-core-version}')
+}
+----
+====
 
-Plugin factory fields and parameters can be automatically validated at runtime using constraint validators inspired by the Bean Validation spec. The following annotations are bundled in Log4j, but custom ConstraintValidators can be created as well.
+[#plugin-discovery]
+== Discovering plugins
 
-* Required: This annotation validates that a value is non-empty. This covers a check for null as well as several other scenarios: empty CharSequence objects, empty arrays, empty Collection instances, and empty Map instances.
-* ValidHost: This annotation validates that a value corresponds to a valid hostname. This uses the same validation as InetAddress::getByName.
-* ValidPort: This annotation validates that a value corresponds to a valid port number between 0 and 65535.
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/util/PluginManager.html[`PluginManager`] is responsible for discovering plugins and loading their descriptions.
+It locates plugins by looking in following places in given order:
 
-[#key-providers]
-== Key providers
+. Plugin descriptor files on the classpath (using the class loader that loaded the `log4j-core` artifact).
+These files are generated automatically at compile-time by the Log4j plugin annotation processor.
+See <<plugin-registry>> for details.
 
-Some components within Log4j may provide the ability to perform data encryption. These components require a secret key to perform the encryption. Applications may provide the key by creating a class that implements the SecretKeyProvider interface.
+. *[OSGi only]* Serialized plugin listing files in each active OSGi bundle.
+A `BundleListener` is added on activation to continue checking new bundles after Log4j Core has started.
 
-[#lookups]
-== Lookups
+. *[Deprecated]* A comma-separated list of packages specified by the `log4j.plugin.packages` system property
 
-Lookups are perhaps the simplest plugins of all. They must declare their type as "Lookup" on the plugin annotation and must implement the StrLookup interface. They will have two methods; a lookup method that accepts a String key and returns a String value and a second lookup method that accepts both a LogEvent and a String key and returns a String. Lookups may be referenced by specifying ${name:key} where name is the name specified in the Plugin annotation and key is the name of the item [...]
+. *[Deprecated]* Packages passed to the static `PluginManager.addPackages()` method before Log4j configuration takes place
 
-[#type-converters]
-== Type converters
+. *[Deprecated]* The `packages` attribute declared at the root element of your Log4j configuration file
 
-TypeConverters are a sort of meta-plugin used for converting strings into other types in a plugin factory method parameter. Other plugins can already be injected via the @PluginElement annotation; now, any type supported by the type conversion system can be used in a @PluginAttribute parameter. Conversion of enum types are supported on demand and do not require custom TypeConverter classes. A large number of built-in Java classes are already supported; see TypeConverters for a more exhau [...]
+[#plugin-load]
+== Loading plugins
 
-Unlike other plugins, the plugin name of a TypeConverter is purely cosmetic. Appropriate type converters are looked up via the Type interface rather than via Class<?> objects only. Do note that TypeConverter plugins must have a default constructor. When multiple converters match for a type, the first will be returned. If any extends from Comparable<TypeConverter<?>>, it will be used for determining the order.
+It is pretty common that a plugin uses other plugins; appenders accept layouts, some layouts accept key-value pairs, etc.
+You can do this as follows:
 
-[#developer-notes]
-==  Developer notes
+* If your plugin has a <<#declare-plugin-factory,plugin factory>> (i.e., it is represented by a configuration file element), you can use <<#PluginElement, the `@PluginElement` annotation>> to receive other plugins.
+See `@PluginElement("EventTemplateAdditionalField")` usage in {project-github-url}/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/JsonTemplateLayout.java[`JsonTemplateLayout.java`] for an example.
 
-If a plugin class implements Collection or Map, then no factory method is used. Instead, the class is instantiated using the default constructor, and all child configuration nodes are added to the Collection or Map.
+* Otherwise, you can use link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/util/PluginUtl.html[`PluginUtil`], which is a convenient wrapper around <<#plugin-discovery,`PluginManager`>>, to discover and load plugins.
+See {project-github-url}/log4j-layout-template-json/src/main/java/org/apache/logging/log4j/layout/template/json/resolver/TemplateResolverFactories.java[`TemplateResolverFactories.java`] for example usages.
diff --git a/src/site/antora/modules/ROOT/partials/configuration-file-format-deps.adoc b/src/site/antora/modules/ROOT/partials/configuration-file-format-deps.adoc
index 9b5e4c2ad5..4126c5e3f2 100644
--- a/src/site/antora/modules/ROOT/partials/configuration-file-format-deps.adoc
+++ b/src/site/antora/modules/ROOT/partials/configuration-file-format-deps.adoc
@@ -23,11 +23,11 @@ Maven::
 [tabs]
 =====
 
-log4j2.xml::
+XML::
 +
 No dependency required.
 
-log4j2.json::
+JSON::
 +
 [source,xml,subs="+attributes"]
 ----
@@ -39,7 +39,7 @@ log4j2.json::
 </dependency>
 ----
 
-log4j2.yaml::
+YAML::
 +
 [source,xml,subs="+attributes"]
 ----
@@ -51,7 +51,7 @@ log4j2.yaml::
 </dependency>
 ----
 
-log4j2.properties::
+Properties::
 +
 No dependency required.
 
@@ -62,27 +62,27 @@ Gradle::
 [tabs]
 =====
 
-log4j2.xml::
+XML::
 +
 No dependency required.
 
-log4j2.json::
+JSON::
 +
 [source,groovy,subs="+attributes"]
 ----
 runtimeOnly 'com.fasterxml.jackson.core:jackson-databind:{jackson-version}'
 ----
 
-log4j2.yaml::
+YAML::
 +
 [source,groovy,subs="+attributes"]
 ----
 runtimeOnly 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:{jackson-version}'
 ----
 
-log4j2.properties::
+Properties::
 +
 No dependency required.
 
 =====
-====
\ No newline at end of file
+====
diff --git a/src/site/antora/modules/ROOT/partials/manual/composite-configuration.adoc b/src/site/antora/modules/ROOT/partials/manual/composite-configuration.adoc
new file mode 100644
index 0000000000..89c0ba83d2
--- /dev/null
+++ b/src/site/antora/modules/ROOT/partials/manual/composite-configuration.adoc
@@ -0,0 +1,50 @@
+////
+    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.
+////
+
+// tag::intro[]
+There are occasions where multiple configurations might need to be combined.
+For instance,
+
+* You have a common Log4j Core configuration that should always be present, and an environment-specific one that extends the common one depending on the environment (test, production, etc.) the application is running on.
+* You develop a framework, and it contains a predefined Log4j Core configuration.
+Yet you want to allow users to extend it whenever necessary.
+* You collect Log4j Core configurations from multiple sources.
+// end::intro[]
+
+// tag::how[]
+`CompositeConfiguration` merges multiple configurations into a single one using a link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/composite/MergeStrategy.html[`MergeStrategy`], which can be customized using xref:manual/systemproperties.adoc#log4j2.mergeStrategy[the `log4j2.mergeStrategy` configuration property].
+The default merge strategy works as follows:
+
+* xref:manual/configuration.adoc#global-configuration-attributes[Global configuration attributes] in later configurations replace those in previous configurations.
+The only exception is the `monitorInterval` attribute: the lowest positive value from all the configuration files will be used.
+
+* xref:manual/configuration.adoc#property-substitution[Properties] are aggregated.
+Duplicate properties override those in previous configurations.
+
+* xref:manual/filters.adoc[Filters] are aggregated under xref:manual/filters.adoc#CompositeFilter[`CompositeFilter`], if more than one filter is defined.
+
+* xref:manual/scripts.adoc[] are aggregated.
+Duplicate definitions override those in previous configurations.
+
+* xref:manual/appenders.adoc[Appenders] are aggregated.
+Appenders with the same name are **overridden** by those in later configurations, including all their elements.
+
+* xref:manual/configuration.adoc#configuring-loggers[Loggers] are aggregated.
+Logger attributes are individually merged, and those in later configurations replace duplicates.
+Appender references on a logger are aggregated, and those in later configurations replace duplicates.
+The strategy merges filters on loggers using the rule above.
+// end::how[]
diff --git a/src/site/antora/modules/ROOT/partials/manual/plugin-preliminaries.adoc b/src/site/antora/modules/ROOT/partials/manual/plugin-preliminaries.adoc
index ce00948b59..f15448a511 100644
--- a/src/site/antora/modules/ROOT/partials/manual/plugin-preliminaries.adoc
+++ b/src/site/antora/modules/ROOT/partials/manual/plugin-preliminaries.adoc
@@ -16,7 +16,7 @@
 ////
 
 Log4j plugin system is the de facto extension mechanism embraced by various Log4j components.
-Plugins make it possible for extensible components to _receive_ feature implementations without any explicit links in between.
+Plugins provide extension points to components, that can be used to implement new features, without modifying the original component.
 It is analogous to a https://en.wikipedia.org/wiki/Dependency_injection[dependency injection] framework, but curated for Log4j-specific needs.
 
 In a nutshell, you annotate your classes with link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/Plugin.html[`@Plugin`] and their (`static`) factory methods with link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/plugins/PluginFactory.html[`@PluginFactory`].
diff --git a/src/site/resources/.htaccess b/src/site/resources/.htaccess
index 308ff31b1c..ad47945d85 100644
--- a/src/site/resources/.htaccess
+++ b/src/site/resources/.htaccess
@@ -44,47 +44,6 @@ RewriteRule "^log4j-mongodb3(/index)?\.html$" "manual/appenders.html#NoSQLAppend
 RewriteRule "^log4j-mongodb4(/index)?\.html$" "manual/appenders.html#log4j-mongodb4" [R=permanent,NE]
 RewriteRule "^log4j-slf4j2?-impl(/index)?\.html$" "manual/installation.html#impl-core-bridge-slf4j" [R=permanent,NE]
 RewriteRule "^manual/api-separation\.html$" "manual/api.html" [R=permanent]
-RewriteRule "^manual/extending\.html#Layouts$" "manual/layouts.html#extending" [R=permanent]
-RewriteRule "^manual/extending\.html#PatternConverters$" "manual/pattern-layout.html#extending-converters" [R=permanent]
-RewriteRule "^manual/layouts\.html#enable-jansi$" "manual/pattern-layout.html#jansi" [R=permanent]
-RewriteRule "^manual/layouts\.html#EndOfBatch$" "manual/pattern-layout.html#converter-end-of-batch" [R=permanent]
-RewriteRule "^manual/layouts\.html#LevelPatternSelector$" "manual/pattern-layout.html#plugin-element-LevelPatternSelector" [R=permanent]
-RewriteRule "^manual/layouts\.html#MarkerPatternSelector$" "manual/pattern-layout.html#plugin-element-MarkerPatternSelector" [R=permanent]
-RewriteRule "^manual/layouts\.html#(PatternLayout|pattern-layout)$" "manual/pattern-layout.html" [R=permanent]
-RewriteRule "^manual/layouts\.html#Patterns$" "manual/pattern-layout.html#converters" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternClass$" "manual/pattern-layout.html#converter-class" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternDate$" "manual/pattern-layout.html#converter-date" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternException$" "manual/pattern-layout.html#converter-exception" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternExtendedException$" "manual/pattern-layout.html#converter-exception-extended" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternFile$" "manual/pattern-layout.html#converter-file" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternLevel$" "manual/pattern-layout.html#converter-level" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternLine$" "manual/pattern-layout.html#converter-line" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternLocation$" "manual/pattern-layout.html#converter-location" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternLoggerFqcn$" "manual/pattern-layout.html#converter-fqcn" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternMap$" "manual/pattern-layout.html#converter-map" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternMarker(SimpleName)?$" "manual/pattern-layout.html#converter-marker" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternMaxLength$" "manual/pattern-layout.html#converter-max-len" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternMDC$" "manual/pattern-layout.html#converter-thread-context-map" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternMessage$" "manual/pattern-layout.html#converter-message" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternMethod$" "manual/pattern-layout.html#converter-method" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternNDC$" "manual/pattern-layout.html#converter-thread-context-stack" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternPercentLiteral$" "manual/pattern-layout.html#usage" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternRelative$" "manual/pattern-layout.html#converter-relative" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternRepeat$" "manual/pattern-layout.html#converter-repeat" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternReplace$" "manual/pattern-layout.html#converter-replace" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternSelectors$" "manual/pattern-layout.html#plugin-element-PatternSelector" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternSequenceNumber$" "manual/pattern-layout.html#converter-seq" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternStyle$" "manual/pattern-layout.html#converter-style" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternThreadId$" "manual/pattern-layout.html#converter-thread-id" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternThreadName$" "manual/pattern-layout.html#converter-thread-name" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternThreadPriority$" "manual/pattern-layout.html#converter-thread-priority" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternUUID$" "manual/pattern-layout.html#converter-uuid" [R=permanent]
-RewriteRule "^manual/layouts\.html#NanoTime$" "manual/pattern-layout.html#converter-nano" [R=permanent]
-RewriteRule "^manual/layouts\.html#PatternNewLine$" "manual/pattern-layout.html#usage" [R=permanent]
-RewriteRule "^manual/layouts\.html#Process_ID$" "manual/pattern-layout.html#converter-pid" [R=permanent]
-RewriteRule "^manual/layouts\.html#ScriptPatternSelector$" "manual/pattern-layout.html#plugin-element-ScriptPatternSelector" [R=permanent]
-RewriteRule "^manual/layouts\.html#VariablesNotEmpty$" "manual/pattern-layout.html#converter-not-empty" [R=permanent]
-RewriteRule "^manual/plugins\.html#converters$" "manual/pattern-layout.html#extending-converters" [R=permanent]
 RewriteRule "^manual/scala-api\.html$" "/log4j/scala/latest/index.html" [R=permanent]
 RewriteRule "^manual/usage\.html$" "manual/api.html" [R=permanent]
 RewriteRule "^runtime-dependencies\.html$" "manual/installation.html" [R=permanent]