ramanathan1504 commented on code in PR #4230:
URL: https://github.com/apache/logging-log4j2/pull/4230#discussion_r4029351348


##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/OrderComparator.java:
##########
@@ -39,20 +41,32 @@ public static Comparator<Class<?>> getInstance() {
 
     @Override
     public int compare(final Class<?> lhs, final Class<?> rhs) {
-        final Order lhsOrder = Objects.requireNonNull(lhs, 
"lhs").getAnnotation(Order.class);
-        final Order rhsOrder = Objects.requireNonNull(rhs, 
"rhs").getAnnotation(Order.class);
-        if (lhsOrder == null && rhsOrder == null) {
+        Objects.requireNonNull(lhs, "lhs");
+        Objects.requireNonNull(rhs, "rhs");
+        final OptionalInt lhsOrder = getOrder(lhs);
+        final OptionalInt rhsOrder = getOrder(rhs);
+        if (lhsOrder.isEmpty() && rhsOrder.isEmpty()) {
             // both unannotated means equal priority
             return 0;
         }
-        // if only one class is @Order-annotated, then prefer that one
-        if (rhsOrder == null) {
+        // if only one class is annotated, then prefer that one
+        if (rhsOrder.isEmpty()) {
             return -1;
         }
-        if (lhsOrder == null) {
+        if (lhsOrder.isEmpty()) {
             return 1;
         }
-        // larger value means higher priority
-        return Integer.signum(rhsOrder.value() - lhsOrder.value());
+        // larger value means higher priority (descending order)
+        return Integer.signum(rhsOrder.getAsInt() - lhsOrder.getAsInt());
+    }
+
+    private static OptionalInt getOrder(final Class<?> clazz) {
+        // Check for legacy @Order annotation first

Review Comment:
   ```suggestion
   ```



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/OrderComparator.java:
##########
@@ -39,20 +41,32 @@ public static Comparator<Class<?>> getInstance() {
 
     @Override
     public int compare(final Class<?> lhs, final Class<?> rhs) {
-        final Order lhsOrder = Objects.requireNonNull(lhs, 
"lhs").getAnnotation(Order.class);
-        final Order rhsOrder = Objects.requireNonNull(rhs, 
"rhs").getAnnotation(Order.class);
-        if (lhsOrder == null && rhsOrder == null) {
+        Objects.requireNonNull(lhs, "lhs");
+        Objects.requireNonNull(rhs, "rhs");
+        final OptionalInt lhsOrder = getOrder(lhs);
+        final OptionalInt rhsOrder = getOrder(rhs);
+        if (lhsOrder.isEmpty() && rhsOrder.isEmpty()) {
             // both unannotated means equal priority
             return 0;
         }
-        // if only one class is @Order-annotated, then prefer that one
-        if (rhsOrder == null) {
+        // if only one class is annotated, then prefer that one
+        if (rhsOrder.isEmpty()) {
             return -1;
         }
-        if (lhsOrder == null) {
+        if (lhsOrder.isEmpty()) {
             return 1;
         }
-        // larger value means higher priority
-        return Integer.signum(rhsOrder.value() - lhsOrder.value());
+        // larger value means higher priority (descending order)
+        return Integer.signum(rhsOrder.getAsInt() - lhsOrder.getAsInt());
+    }
+
+    private static OptionalInt getOrder(final Class<?> clazz) {
+        // Check for legacy @Order annotation first
+        final Order order = clazz.getAnnotation(Order.class);
+        if (order != null) {
+            return OptionalInt.of(order.value());
+        }
+        // Fall back to @Ordered via AnnotationUtil
+        return AnnotationUtil.getOrder(clazz);

Review Comment:
   `OrderedComparator` sorts `@Ordered` smallest first and `Ordered.FIRST` is 
`Integer.MIN_VALUE`, but here it sorts largest first. So 
`@Ordered(Ordered.FIRST)` on a factory ends up last. Should factories keep 
`@Order`, or should this comparator follow the `@Ordered` direction? A test in 
`log4j-core-test` for either answer would pin it. cc @jvz



##########
log4j-core/src/main/java/org/apache/logging/log4j/core/config/OrderComparator.java:
##########
@@ -39,20 +41,32 @@ public static Comparator<Class<?>> getInstance() {
 
     @Override
     public int compare(final Class<?> lhs, final Class<?> rhs) {
-        final Order lhsOrder = Objects.requireNonNull(lhs, 
"lhs").getAnnotation(Order.class);
-        final Order rhsOrder = Objects.requireNonNull(rhs, 
"rhs").getAnnotation(Order.class);
-        if (lhsOrder == null && rhsOrder == null) {
+        Objects.requireNonNull(lhs, "lhs");
+        Objects.requireNonNull(rhs, "rhs");
+        final OptionalInt lhsOrder = getOrder(lhs);
+        final OptionalInt rhsOrder = getOrder(rhs);
+        if (lhsOrder.isEmpty() && rhsOrder.isEmpty()) {
             // both unannotated means equal priority
             return 0;
         }
-        // if only one class is @Order-annotated, then prefer that one
-        if (rhsOrder == null) {
+        // if only one class is annotated, then prefer that one
+        if (rhsOrder.isEmpty()) {
             return -1;
         }
-        if (lhsOrder == null) {
+        if (lhsOrder.isEmpty()) {
             return 1;
         }
-        // larger value means higher priority
-        return Integer.signum(rhsOrder.value() - lhsOrder.value());
+        // larger value means higher priority (descending order)
+        return Integer.signum(rhsOrder.getAsInt() - lhsOrder.getAsInt());
+    }
+
+    private static OptionalInt getOrder(final Class<?> clazz) {
+        // Check for legacy @Order annotation first
+        final Order order = clazz.getAnnotation(Order.class);
+        if (order != null) {
+            return OptionalInt.of(order.value());
+        }
+        // Fall back to @Ordered via AnnotationUtil

Review Comment:
   ```suggestion
   ```



##########
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 `@Ordered` value)

Review Comment:
   This depends on the `OrderComparator` answer. With `Ordered.FIRST` it reads 
the other way.
   
   Cut from the posted comment, kept here: the per-anchor list of broken xrefs 
(the website build prints it), the unswept `@Order` on 
`YamlConfigurationFactory` / `JavaPropsConfigurationFactory` / OSGi test 
factory (depends on the maintainer answer), the #3161 port-format and changelog 
rule, no CI run, and `filters.adoc` inline anchor (covered by the summary line).



##########
src/site/antora/modules/ROOT/pages/manual/appenders.adoc:
##########
@@ -136,445 +159,3899 @@ This behavior can be changed using the following 
configuration property:
 [#ignoreExceptions]
 ==== `ignoreExceptions`
 
-[cols="1h,5"]
-|===
-| Type          | `boolean`
-| Default value | `true`
-|===
+|bufferSize |integer a|
+Specifies the maximum number of events that can be queued. The default
+is 1024. Note that when using a disruptor-style `BlockingQueue`, this
+buffer size must be a power of 2.
 
-If `false` logging exceptions will be forwarded to the caller.
-Otherwise, they will be logged using the
-{log4j2-url}/manual/status-logger.html[status logger].
+When the application is logging faster than the underlying appender can
+keep up with for a long enough time to fill up the queue, the behavior
+is determined by the
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/AsyncQueueFullPolicy.html[`AsyncQueueFullPolicy`].
 
-[TIP]
-====
-If logging is important for your business, consider using a
-xref:manual/appenders/delegating.adoc#FailoverAppender[`Failover` Appender]
-to redirect log events to a different appender in case of exceptions.
-====
+|errorRef |String |The name of the Appender to invoke if none of the
+appenders can be called, either due to errors in the appenders or
+because the queue is full. If not specified then errors will be ignored.
 
-[#runtime-evaluation]
-=== Runtime evaluation of attributes
+|filter |Filter |A Filter to determine if the event should be handled by
+this Appender. More than one Filter may be used by using a
+CompositeFilter.
 
-The following configuration attributes are also evaluated at runtime, so can 
contain escaped `$$+{...}+` property substitution expressions.
+|name |String |The name of the Appender.
 
-.List of attributes evaluated at runtime
-[cols="1,1,1,1"]
-|===
-| Component | Parameter | Event type | Evaluation context
+|ignoreExceptions |boolean |The default is `true`, causing exceptions
+encountered while appending events to be internally logged and then
+ignored. When set to `false` exceptions will be propagated to the
+caller, instead. You must set this to `false` when wrapping this
+Appender in a <FailoverAppender>>.
 
-| xref:manual/appenders/network.adoc#HttpAppender[HTTP Appender]
-| 
xref:manual/appenders/network.adoc#HttpAppender-element-Property[`Property/value`]
-| Log event
-| xref:manual/lookups.adoc#global-context[_global_]
+|includeLocation |boolean |Extracting location is an expensive operation
+(it can make logging 5 - 20 times slower). To improve performance,
+location is not included by default when adding a log event to the
+queue. You can change this by setting includeLocation="true".
 
-| xref:manual/appenders/database.adoc#NoSqlAppender[NoSQL Appender]
-| 
xref:manual/appenders/database.adoc#NoSqlAppender-element-KeyValuePair[`KeyValuePair/value`]
-| Log event
-| xref:manual/lookups.adoc#global-context[_global_]
+|BlockingQueueFactory
+|BlockingQueueFactory
+|This element overrides what type of `BlockingQueue` to use.
+See <<BlockingQueueFactory,below documentation>> for more details.
+|=======================================================================
 
-| 
xref:manual/appenders/delegating.adoc#PropertiesRewritePolicy[PropertiesRewrite 
Policy]
-| 
xref:manual/appenders/delegating.adoc#PropertiesRewritePolicy-element-Property[`Property/value`]
-| Log event
-| xref:manual/lookups.adoc#global-context[_global_]
+There are also a few system properties that can be used to maintain 
application throughput even when the underlying appender cannot keep up with 
the logging rate and the queue is filling up.
+See the details for system properties
+xref:manual/systemproperties.adoc#log4j.async.queueFullPolicy.type[`log4j.async.queueFullPolicy.type`]
+and
+xref:manual/systemproperties.adoc#log4j.async.queueFullPolicy.discardThreshold[`log4j.async.queueFullPolicy.discardThreshold`].
 
-| xref:manual/appenders/delegating.adoc#Routes[Routes Container]
-| xref:manual/appenders/delegating.adoc#Routes-attr-pattern[`pattern`]
-| Log event
-| xref:manual/lookups.adoc#event-context[_log event_]
+A typical AsyncAppender configuration might look like this:
 
-| xref:manual/appenders/rolling-file.adoc[Rolling File Appenders]
-| xref:manual/appenders/rolling-file.adoc#attr-filePattern[`filePattern`]
-| Rollover
-| xref:manual/lookups.adoc#global-context[_global_]
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="warn" name="MyApp">
+  <Appenders>
+    <File name="MyFile" fileName="logs/app.log">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+    </File>
+    <Async name="Async">
+      <AppenderRef ref="MyFile"/>
+    </Async>
+  </Appenders>
+  <Loggers>
+    <Root level="error">
+      <AppenderRef ref="Async"/>
+    </Root>
+  </Loggers>
+</Configuration>
+----
 
-| xref:manual/appenders/rolling-file.adoc#AbstractPathAction[Optional Rollover 
Actions]
-| 
xref:manual/appenders/rolling-file.adoc#AbstractPathAction-attr-basePath[`basePath`]
-| Rollover
-| xref:manual/lookups.adoc#global-context[_global_]
+[[BlockingQueueFactory]]
+Starting in Log4j 2.7, a custom implementation of `BlockingQueue` or 
`TransferQueue` can be specified using a
+link:../javadoc/log4j-core/org/apache/logging/log4j/core/async/BlockingQueueFactory.html[`BlockingQueueFactory`]
+plugin.
+To override the default `BlockingQueueFactory`, specify the plugin inside an 
`<Async/>` element like so:
 
-|===
+[source,xml]
+----
+<Configuration name="LinkedTransferQueueExample">
+  <Appenders>
+    <List name="List"/>
+    <Async name="Async" bufferSize="262144">
+      <AppenderRef ref="List"/>
+      <LinkedTransferQueue/>
+    </Async>
+  </Appenders>
+  <Loggers>
+    <Root>
+      <AppenderRef ref="Async"/>
+    </Root>
+  </Loggers>
+</Configuration>
+----
 
-The
-xref:manual/appenders/delegating.adoc#Route[`Route`]
-component of the
-xref:manual/appenders/delegating.adoc#RoutingAppender[Routing Appender]
-is special: its children are evaluated at runtime, but they are **not** 
evaluated at configuration time.
-Inside the `Route` component you **should not** use escaped `$$+{...}+` 
property substitution expressions, but only unescaped `$+{...}+` property 
substitution expressions.
+Log4j ships with the following implementations:
+
+.BlockingQueueFactory Implementations
+[cols="25%,75%",options="header",]
+|=======================================================================
+|Plugin Name |Description
+|ArrayBlockingQueue |This is the default implementation that uses
+https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ArrayBlockingQueue.html[`ArrayBlockingQueue`].
+
+|DisruptorBlockingQueue |This uses the
+https://github.com/conversant/disruptor[Conversant Disruptor]
+implementation of `BlockingQueue`. This plugin takes a single optional
+attribute, `spinPolicy`, which corresponds to the `SpinPolicy` enum.
+
+|JCToolsBlockingQueue |This uses
+https://jctools.github.io/JCTools/[JCTools], specifically the MPSC
+bounded lock-free queue.
+This implementation is provided by the `log4j-jctools` artifact.
+
+|LinkedTransferQueue |This uses the new Java 7 implementation
+https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedTransferQueue.html[`LinkedTransferQueue`].
+Note that this queue does not use the `bufferSize` configuration
+attribute from AsyncAppender as `LinkedTransferQueue` does not support a
+maximum capacity.
+|=======================================================================
+
+[id=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.
+A Layout must be provided to format the LogEvent.
+
+.ConsoleAppender Parameters
+[cols="20%,20%,60%",options="header",]
+|=======================================================================
+|Parameter Name |Type |Description
+|filter |Filter |A Filter to determine if the event should be handled by
+this Appender. More than one Filter may be used by using a
+CompositeFilter.
+
+|layout |Layout |The Layout to use to format the LogEvent. If no layout
+is supplied the default pattern layout of "%m%n" will be used.
+
+|follow |boolean |Identifies whether the appender honors reassignments
+of `System.out` or `System.err` via `System.setOut` or `System.setErr` made
+after configuration. Note that the follow attribute cannot be used with
+Jansi on Windows. Cannot be used with `direct`.
+
+|direct |boolean |Write directly to `java.io.FileDescriptor` and bypass
+`java.lang.System.out/.err`. Can give up to 10x performance boost when
+the output is redirected to a file or other process. Cannot be used with
+Jansi on Windows. Cannot be used with `follow`. The output will not respect
+`java.lang.System.setOut()/.setErr()` and may get intertwined with other
+output to `java.lang.System.out/.err` in a multi-threaded application.
+_New since 2.6.2. Be aware that this is a new addition, and it has only
+been tested with Oracle JVM on Linux and Windows so far._
+
+|name |String |The name of the Appender.
+
+|ignoreExceptions |boolean |The default is `true`, causing exceptions
+encountered while appending events to be internally logged and then
+ignored. When set to `false` exceptions will be propagated to the
+caller, instead. You must set this to `false` when wrapping this
+Appender in a <<FailoverAppender>>.
+
+|target |String |Either "SYSTEM_OUT" or "SYSTEM_ERR". The default is
+"SYSTEM_OUT".
+|=======================================================================
+
+A typical Console configuration might look like:
+
+[source,xml,prettyprint,linenums]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="warn" name="MyApp">
+  <Appenders>
+    <Console name="STDOUT" target="SYSTEM_OUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+</Configuration>
+----
 
-See xref:manual/configuration.adoc#lazy-property-substitution[runtime property 
substitution] for more details.
+[#FailoverAppender]
+=== FailoverAppender
 
-[#collection]
-== Collection
+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.
 
-Log4j bundles several predefined appenders to assist in several common 
deployment use cases.
-They are documented in separate pages based on their target resource:
+.FailoverAppender Parameters
+[cols="20%,20%,60%",options="header",]
+|=======================================================================
+|Parameter Name |Type |Description
+|filter |Filter |A Filter to determine if the event should be handled by
+this Appender. More than one Filter may be used by using a
+CompositeFilter.
 
-[#ConsoleAppender]
-=== Console Appender
+|primary |String |The name of the primary Appender to use.
 
-As one might expect, the Console Appender writes its output to either the 
standard output or standard error output.
-The appender supports three different ways to access the output streams:
+|failovers |String[] |The names of the secondary Appenders to use.
 
-`direct`::
-This mode gives the best performance.
-It can be enabled by setting the <<ConsoleAppender-attr-direct,`direct`>> 
attribute to `true`.
+|name |String |The name of the Appender.
 
-`default`::
-By default, the Console appender uses the values of `System.out` or 
`System.err` present at **configuration time**.
-Any changes to those streams at runtime will be ignored.
+|retryIntervalSeconds |integer |The number of seconds that should pass
+before retrying the primary Appender. The default is 60.
 
-`follow`::
-This mode always uses the **current** value of the `System.out` and 
`System.err` streams.
-It can be enabled by setting the <<ConsoleAppender-attr-follow,`follow`>> 
attribute to `true`.
-+
-[TIP]
-====
-This setting might be useful in multi-application environments.
-Some application servers modify `System.out` and `System.err` to always point 
to the currently running application.
-====
+|ignoreExceptions |boolean |The default is `true`, causing exceptions
+encountered while appending events to be internally logged and then
+ignored. When set to `false` exceptions will be propagated to the
+caller, instead.
 
-[#ConsoleAppender-attributes]
-.Console Appender configuration attributes
-[cols="1m,1,1,5"]
-|===
-| Attribute | Type | Default value | Description
+|target |String |Either "SYSTEM_OUT" or "SYSTEM_ERR". The default is
+"SYSTEM_ERR".
+|=======================================================================
 
-4+h| Required
+A Failover configuration might look like:
 
-| [[ConsoleAppender-attr-name]]name
-| `String`
-|
-| The name of the appender.
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="warn" name="MyApp">
+  <Appenders>
+    <RollingFile name="RollingFile" fileName="logs/app.log" 
filePattern="logs/app-%d{MM-dd-yyyy}.log.gz"
+                 ignoreExceptions="false">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+      <TimeBasedTriggeringPolicy />
+    </RollingFile>
+    <Console name="STDOUT" target="SYSTEM_OUT" ignoreExceptions="false">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+    <Failover name="Failover" primary="RollingFile">
+      <Failovers>
+        <AppenderRef ref="Console"/>
+      </Failovers>
+    </Failover>
+  </Appenders>
+  <Loggers>
+    <Root level="error">
+      <AppenderRef ref="Failover"/>
+    </Root>
+  </Loggers>
+</Configuration>
+----
 
-4+h| Optional
+[id=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.
+While FileAppenders from different Configurations cannot be shared, the 
FileManagers can be if the Manager is accessible.
+For example, two web applications in a servlet container can have their 
configuration and safely write to the same file if Log4j is in a ClassLoader 
that is common to both of them.
+
+.FileAppender Parameters
+[width="100%",cols="20%,20%,60%",options="header",]
+|=======================================================================
+|Parameter Name |Type |Description
+|append |boolean |When true - the default, records will be appended to
+the end of the file. When set to false, the file will be cleared before
+new records are written.
+
+|bufferedIO |boolean |When true - the default, records will be written
+to a buffer and the data will be written to disk when the buffer is full
+or, if immediateFlush is set, when the record is written. File locking
+cannot be used with `bufferedIO`. Performance tests have shown that using
+buffered I/O significantly improves performance, even if `immediateFlush`
+is enabled.
+
+|bufferSize |int |When `bufferedIO` is true, this is the buffer size, the
+default is 8192 bytes.
+
+|createOnDemand |boolean |The appender creates the file on-demand. The
+appender only creates the file when a log event passes all filters and
+is routed to this appender. Defaults to false.
+
+|filter |Filter |A Filter to determine if the event should be handled by
+this Appender. More than one Filter may be used by using a
+CompositeFilter.
+
+|fileName |String |The name of the file to write to. If the file, or any
+of its parent directories, do not exist, they will be created.
+
+|immediateFlush |boolean a|
+When set to true - the default, each write will be followed by a flush.
+This will guarantee that the data is passed to the operating system for 
writing;
+it does not guarantee that the data is written to a physical device
+such as a disk drive.
+
+Note that if this flag is set to false, and the logging activity is sparse,
+there may be an indefinite delay in the data eventually making it to the
+operating system, because it is held up in a buffer.
+This can cause surprising effects such as the logs not
+appearing in the tail output of a file immediately after writing to the log.
+
+Flushing after every write is only useful when using this appender with
+synchronous loggers. Asynchronous loggers and appenders will
+automatically flush at the end of a batch of events, even if
+immediateFlush is set to false. This also guarantees the data is passed
+to the operating system but is more efficient.
+
+|layout |Layout |The Layout to use to format the LogEvent. If no layout
+is supplied the default pattern layout of "%m%n" will be used.
+
+|locking |boolean |When set to true, I/O operations will occur only
+while the file lock is held allowing FileAppenders in multiple JVMs and
+potentially multiple hosts to write to the same file simultaneously.
+This will significantly impact performance so should be used carefully.
+Furthermore, on many systems, the file lock is "advisory" meaning that
+other applications can perform operations on the file without acquiring
+a lock. The default value is false.
+
+|name |String |The name of the Appender.
+
+|ignoreExceptions |boolean |The default is `true`, causing exceptions
+encountered while appending events to be internally logged and then
+ignored. When set to `false` exceptions will be propagated to the
+caller, instead. You must set this to `false` when wrapping this
+Appender in a <<FailoverAppender>>.
+
+|filePermissions |String a|
+File attribute permissions in POSIX format to apply whenever the file is
+created.
+
+The underlying files system shall support
+https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
+file attribute view.
+
+Examples: `rw-------` or `rw-rw-rw-` etc...
+
+|fileOwner |String a|
+File owner to define whenever the file is created.
+
+Changing the file's owner may be restricted for security reasons and
+Operation not permitted IOException thrown. Only processes with an
+effective user ID equal to the user ID of the file or with appropriate
+privileges may change the ownership of a file if
+http://www.gnu.org/software/libc/manual/html_node/Options-for-Files.html[_POSIX_CHOWN_RESTRICTED]
+is in effect for path.
+
+The underlying files system shall support file
+https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/FileOwnerAttributeView.html[owner]
+attribute view.
+
+|fileGroup |String a|
+File group to define whenever the file is created.
+
+The underlying files system shall support
+https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/PosixFileAttributeView.html[POSIX]
+file attribute view.
+
+|=======================================================================
+
+Here is a sample File configuration:
+
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="warn" name="MyApp">
+  <Appenders>
+    <File name="MyFile" fileName="logs/app.log">
+      <PatternLayout>
+        <Pattern>%d %p %c{1.} [%t] %m%n</Pattern>
+      </PatternLayout>
+    </File>
+  </Appenders>
+  <Loggers>
+    <Root level="error">
+      <AppenderRef ref="MyFile"/>
+    </Root>
+  </Loggers>
+</Configuration>
+----
 
-| [[ConsoleAppender-attr-bufferSize]]bufferSize
-| `int`
-| xref:manual/systemproperties.adoc#log4j.gc.encoderByteBufferSize[`8192`]
-a|
-The size of the
-https://docs.oracle.com/javase/{java-target-version}/docs/api/java/nio/ByteBuffer.html[`ByteBuffer`]
-internally used by the appender.
+[#FlumeAppender]
+=== FlumeAppender

Review Comment:
   Flume, JMS, Kafka, JPA, SMTP and JeroMQ appenders are not in 3.x, and 
Failover, Rewrite, Http and RollingFile are already in `appenders/*.adoc`. Can 
this page be `main`'s version plus only the #2696 changes?



##########
src/site/antora/modules/ROOT/pages/manual/configuration.adoc:
##########
@@ -99,6 +93,13 @@ include::partial$configuration-file-format-deps.adoc[]
 Starting with Log4j 2, the configuration file syntax has been considered part 
of the public API and has remained stable across significant version upgrades.
 ====
 
+[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].
+====

Review Comment:
   `manual/migration.adoc` does not exist on `main`, and Log4j 3 has no Log4j 1 
config support.
   ```suggestion
   ```



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

To unsubscribe, e-mail: [email protected]

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

Reply via email to