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/06/24 18:23:50 UTC
(logging-log4j2) branch doc/2.x/extending created (now e5b8161b08)
This is an automated email from the ASF dual-hosted git repository.
vy pushed a change to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
at e5b8161b08 Revamp `extending.adoc`
This branch includes the following new commits:
new f9deaaf961 Move extending appenders/filters/lookups to their own pages
new 08d942ba74 Improve extending layouts
new 3c20113fea Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
new d495947f48 Rewrite `plugins.adoc`
new 65b9924f21 Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
new fc1953b845 Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
new e5b8161b08 Revamp `extending.adoc`
The 7 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(logging-log4j2) 05/07: Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 65b9924f21d04e60271008a028c7a655d318a54a
Merge: d495947f48 2c8790d406
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Thu Jun 13 11:02:46 2024 +0200
Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
.github/workflows/labeler.yaml | 8 +-
log4j-parent/pom.xml | 2 +-
src/changelog/.2.x.x/update_io_netty_netty_bom.xml | 4 +-
.../manual/migration/Migration1Example.java | 33 +
.../manual/migration/Migration2Example.java | 32 +
.../modules/ROOT/images/whichjar-log4j-1.2-api.png | Bin 24992 -> 0 bytes
.../modules/ROOT/images/whichjar-log4j-api.png | Bin 16515 -> 0 bytes
src/site/antora/modules/ROOT/nav.adoc | 12 +-
src/site/antora/modules/ROOT/pages/faq.adoc | 2 +-
.../antora/modules/ROOT/pages/log4j-1.2-api.adoc | 85 ---
.../pages/log4j-spring-cloud-config-client.adoc | 2 +-
.../antora/modules/ROOT/pages/log4j-taglib.adoc | 2 +-
src/site/antora/modules/ROOT/pages/manual/api.adoc | 8 +-
.../modules/ROOT/pages/manual/appenders.adoc | 218 +++---
.../antora/modules/ROOT/pages/manual/async.adoc | 24 +-
.../antora/modules/ROOT/pages/manual/cloud.adoc | 2 +-
.../modules/ROOT/pages/manual/configuration.adoc | 35 +-
.../modules/ROOT/pages/manual/customconfig.adoc | 2 +-
.../modules/ROOT/pages/manual/customloglevels.adoc | 2 +-
.../modules/ROOT/pages/manual/eventlogging.adoc | 4 +-
.../modules/ROOT/pages/manual/extending.adoc | 4 +-
.../antora/modules/ROOT/pages/manual/filters.adoc | 6 +-
.../modules/ROOT/pages/manual/garbagefree.adoc | 30 +-
.../modules/ROOT/pages/manual/getting-started.adoc | 16 +-
.../modules/ROOT/pages/manual/installation.adoc | 16 +-
src/site/antora/modules/ROOT/pages/manual/jmx.adoc | 11 +-
.../ROOT/pages/manual/json-template-layout.adoc | 112 +--
.../antora/modules/ROOT/pages/manual/layouts.adoc | 38 +-
.../antora/modules/ROOT/pages/manual/logsep.adoc | 2 +-
.../antora/modules/ROOT/pages/manual/lookups.adoc | 16 +-
.../antora/modules/ROOT/pages/manual/messages.adoc | 38 +-
.../modules/ROOT/pages/manual/migration.adoc | 820 ++++++++++++---------
.../modules/ROOT/pages/manual/pattern-layout.adoc | 124 ++--
.../modules/ROOT/pages/manual/performance.adoc | 4 +-
.../antora/modules/ROOT/pages/manual/plugins.adoc | 2 +-
.../antora/modules/ROOT/pages/manual/scripts.adoc | 8 +-
.../modules/ROOT/pages/manual/status-logger.adoc | 10 +-
.../ROOT/pages/manual/systemproperties.adoc | 10 +-
.../modules/ROOT/pages/manual/thread-context.adoc | 4 +-
.../antora/modules/ROOT/pages/manual/webapp.adoc | 6 +-
.../ROOT/partials/manual/async-trade-offs.adoc | 3 +-
.../manual/layouts-location-information.adoc | 2 +-
.../properties-async-logger-config.adoc | 24 +-
.../systemproperties/properties-async-logger.adoc | 32 +-
.../manual/systemproperties/properties-async.adoc | 14 +-
.../properties-configuration-factory.adoc | 24 +-
.../properties-context-selector.adoc | 21 +-
.../properties-garbage-collection.adoc | 30 +-
.../manual/systemproperties/properties-jansi.adoc | 2 +-
.../manual/systemproperties/properties-jmx.adoc | 4 +-
.../manual/systemproperties/properties-jndi.adoc | 10 +-
.../systemproperties/properties-loader-util.adoc | 2 +-
.../systemproperties/properties-log4j-12-api.adoc | 55 ++
.../properties-log4j-core-misc.adoc | 86 +--
.../systemproperties/properties-log4j-jul.adoc | 24 +-
.../properties-log4j-spring-boot.adoc | 2 +-
.../manual/systemproperties/properties-meta.adoc | 6 +-
.../systemproperties/properties-provider.adoc | 16 +-
.../systemproperties/properties-simple-logger.adoc | 24 +-
.../systemproperties/properties-status-logger.adoc | 24 +-
.../properties-thread-context.adoc | 18 +-
.../properties-transport-security.adoc | 84 +--
src/site/resources/.htaccess | 28 +-
63 files changed, 1222 insertions(+), 1067 deletions(-)
diff --cc src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index be44a32d4d,5e8300a271..d710b4be8e
--- a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
@@@ -1257,7 -1251,8 +1257,8 @@@ table based on a Log4j `MapMessage` ins
</Configuration>
----
- === JMS Appender
+ [#jms-appender]
-== [[JMSAppender]]JMS Appender
++=== [[JMSAppender]]JMS Appender
The JMS Appender sends the formatted log event to a JMS Destination.
@@@ -1986,10 -1981,10 +1987,10 @@@ If you are note sure, which implementat
====
[#log4j-mongodb]
-==== NoSQL provider for MongoDB (current)
+===== NoSQL provider for MongoDB (current)
This section details specializations of the
- link:#NoSQLAppender[NoSQLAppender] provider for MongoDB using the current MongoDB driver (version 5).
+ <<NoSQLAppender>> provider for MongoDB using the current MongoDB driver (version 5).
The NoSQLAppender Appender writes log events to a NoSQL database using an internal lightweight provider interface.
.MongoDB Provider Parameters
@@@ -2075,12 -2070,12 +2076,12 @@@ You can define additional fields to lo
----
[#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 link:#log4j-mongodb[NoSQL provider for MongoDB].
+ The `log4j-mongodb4` module is deprecated in favor of <<log4j-mongodb,NoSQL provider for MongoDB>>.
This section details specializations of the
- link:#NoSQLAppender[NoSQLAppender] provider for MongoDB using the MongoDB driver version 4. The NoSQLAppender Appender writes log events to a NoSQL database using an internal lightweight provider interface.
+ <<NoSQLAppender>> provider for MongoDB using the MongoDB driver version 4. The NoSQLAppender Appender writes log events to a NoSQL database using an internal lightweight provider interface.
.MongoDB Provider Parameters
[cols="20%,20%,60%",options="header",]
@@@ -2165,9 -2160,9 +2166,9 @@@ You can define additional fields to lo
----
[[NoSQLAppenderApacheCouchDB]]
-== NoSQLAppender for Apache CouchDB
+=== NoSQLAppender for Apache CouchDB
- This section details specializations of the link:#NoSQLAppender[NoSQLAppender] provider for 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.
[width="100%",options="header"]
@@@ -2236,10 -2231,10 +2237,10 @@@ Support for immediateFlush and bufferin
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
- link:#FileAppender[FileAppender] except it is always buffered (this cannot be switched off) and internally it uses a
+ <<FileAppender>> except it is always buffered (this cannot be switched off) and internally it uses a
`ByteBuffer + RandomAccessFile` instead of a `BufferedOutputStream`.
We saw a 20-200% performance improvement compared to FileAppender with "bufferedIO=true" in our
measurements.
@@@ -2667,7 -2659,8 +2665,8 @@@ When running in Google App Engine, the
`java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()`
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`.
@@@ -2678,7 -2671,8 +2677,8 @@@ When combined with a time-based trigger
Otherwise, the target file will be overwritten on every rollover as the SizeBased Triggering Policy will not cause the timestamp value in the file name to change.
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
@@@ -3405,10 -3397,10 +3403,10 @@@ Below is a sample configuration that us
----
[#RollingRandomAccessFileAppender]
-== RollingRandomAccessFileAppender
+=== RollingRandomAccessFileAppender
The RollingRandomAccessFileAppender is similar to the standard
- link:#RollingFileAppender[RollingFileAppender] except it is always buffered (this cannot be switched off) and internally it uses a
+ <<RollingFileAppender>> except it is always buffered (this cannot be switched off) and internally it uses a
`ByteBuffer + RandomAccessFile` instead of a `BufferedOutputStream`.
We saw a 20-200% performance improvement compared to RollingFileAppender with "bufferedIO=true" in our measurements.
The
@@@ -3517,13 -3509,13 +3515,13 @@@ file attribute view
|=======================================================================
-=== Triggering Policies
+==== Triggering Policies
- See xref:#TriggeringPolicies[RollingFileAppender Triggering Policies].
+ See <<TriggeringPolicies,RollingFileAppender Triggering Policies>>.
-=== Rollover Strategies
+==== Rollover Strategies
- See link:#RolloverStrategies[RollingFileAppender Rollover Strategies].
+ See <<RolloverStrategies,`RollingFileAppender` rollover strategies>>.
Below is a sample configuration that uses a RollingRandomAccessFileAppender with both the time and size-based triggering policies will create up to 7 archives on the same day (1-7) that are stored in a directory based on the current year and month, and will compress each archive using gzip:
@@@ -4468,45 -4460,3 +4466,45 @@@ Please consult the JeroMQ and ZeroMQ do
|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`]
+* The `elementType` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html#ELEMENT_TYPE[`Appender.ELEMENT_TYPE`]
+
+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 xref:#collection[the predefined appenders], and either use an existing manager, or create your own.
++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`] – xref:#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`] – xref:#ConsoleAppender[Console Appender] writes log events to either `System.out` or `System.err` using `OutputStreamManager`
++* {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 --cc src/site/antora/modules/ROOT/pages/manual/filters.adoc
index 88e10b79ac,baea1d507b..0d13dc97e3
--- a/src/site/antora/modules/ROOT/pages/manual/filters.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/filters.adoc
@@@ -1044,36 -1037,3 +1044,36 @@@ A sample configuration that only allow
</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 xref:#collection[the predefined filter collection] should address most common use cases, you might find yourself needing to implement a custom one.
++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`]
+* The `elementType` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/Filter.html#ELEMENT_TYPE[`Filter.ELEMENT_TYPE`]
+
+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`] – xref:#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`] – xref:#RegexFilter[] matching on the message associated with the effective `LogEvent` in the context
++* {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 --cc src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
index e776c37267,c8736c8ef1..03c12c8fb1
--- a/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/garbagefree.adoc
@@@ -56,8 -56,8 +56,8 @@@ If not for yours, keep on reading
In order to have a garbage-free Log4j Core, you need to
- * xref:#core-properties[configure it using properties],
- * and employ garbage-free xref:#Layouts[layouts], xref:Appenders[appenders], and xref:#Filters[filters].
+ * <<core-properties,configure it using properties>>,
-* and employ garbage-free <<Layouts[layouts], xref:Appenders[appenders], and xref:#Filters,filters>>.
++* and employ garbage-free <<Layouts>>, <<Appenders>>, and <<Filters>>.
[#core-properties]
=== Properties
diff --cc src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc
index 8408762e53,016450092c..bd877a3aa1
--- a/src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/json-template-layout.adoc
@@@ -16,7 -16,7 +16,7 @@@
////
= JSON Template Layout
- `JsonTemplateLayout` is a customizable, xref:#performance[efficient], and xref:#faq-garbage-free[garbage-free] JSON generating layout.
-`JsonTemplateLayout` is a customizable, <<performance,efficient>>, and xref:#faq-garbage-free,garbage-free>> JSON generating layout.
++`JsonTemplateLayout` is a customizable, <<performance,efficient>>, and <<faq-garbage-free,garbage-free>> JSON generating layout.
It encodes ``LogEvent``s according to the structure described by the JSON template provided.
In a nutshell, it shines with its
diff --cc src/site/antora/modules/ROOT/pages/manual/lookups.adoc
index 33e9749801,3b24c6ee4d..41c17fd577
--- a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
@@@ -708,34 -698,3 +708,34 @@@ located then the corresponding value wi
<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 xref:#collection[the predefined lookup collection] should address most common use cases, you might find yourself needing to implement a custom one.
++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`] – xref:#LowerLookup[] lower-cases its input
- * {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/EventLookup.java[`EventLookup.java`] – xref:#EventLookup[] extracts specified fields from the effective `LogEvent` in the context
++* {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 --cc src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
index 97c7433800,fac5648b2a..3c8d838053
--- a/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/pattern-layout.adoc
@@@ -17,7 -17,7 +17,7 @@@
= Pattern Layout
- `PatternLayout` is a customizable, xref:#performance[efficient], xref:#garbage-free[garbage-free], and human-readable string generating layout using a user-provided pattern.
-`PatternLayout` is a customizable, <<performance[efficient], xref:#garbage-free,garbage-free>>, and human-readable string generating layout using a user-provided pattern.
++`PatternLayout` is a customizable, <<performance,efficient>>, <<garbage-free,garbage-free>>, and human-readable string generating layout using a user-provided pattern.
It is analogous to `String#format()` with specialized directives on injecting certain properties of a `LogEvent`.
[IMPORTANT]
@@@ -1596,89 -1596,89 +1596,89 @@@ Format modifiers to control such thing
|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}>>
|
- |xref:#converter-highlight[%highlight\{pattern}\{style}]
+ |<<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>>
|
- |xref:#converter-marker[%marker]
+ |<<converter-marker,%marker>>
|
- |xref:#converter-marker[%markerSimpleName]
+ |<<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>>
|
- |xref:#converter-style[%style\{pattern}{ANSI style}]
+ |<<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>>
|
- |xref:#converter-thread-priority[%tp]
+ |<<converter-thread-priority,%tp>>
|
- |xref:#converter-thread-context-map[%X{key[,key2...\]} +
-|<<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 --cc src/site/antora/modules/ROOT/pages/manual/plugins.adoc
index cbca9ff4ec,c793d404c4..f8beb69933
--- a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
@@@ -14,202 -14,23 +14,202 @@@
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`::
+Denotes the name of the plugin and is recommended to be distinct among plugins sharing the same `category`.
+`name` matching is case-insensitive.
+
+`category`::
+A name used for grouping a set of plugins.
+`name` matching is case-sensitive.
+
+`elementType`::
+Name of the corresponding category of the xref:manual/configuration.adoc[Log4j configuration] file element this plugin belongs under.
+You can omit this attribute if your plugin is not meant to be represented in a configuration file.
+
+For example, xref:manual/lookups.adoc#extending[lookups] only use the `category` attribute and set it to link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html#CATEGORY[`StrLookup.CATEGORY`] (`Lookup`).
+On the other hand, xref:manual/appenders.adoc#extending[appenders] use both the `category` and `elementType` attributes and set them to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`] (`Core`) and link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html#ELEMENT_TYPE[`Appender.ELEMENT_TYPE`] (`appender`), respectively.
+The reason appenders use an `elementType` and lookups don't is that appenders need to be referred to in an element in a Log4j configuration file (e.g., `log4j2.xml`) whereas lookups don't.
+See <<core>> for details.
+
+For clarity's sake, see following examples:
+
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/DateLookup.java[`LowerLookup.java`] (uses only `category`)
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java[`CsvParameterLayout.java`] (uses both `category` and `elementType`)
+
+.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`)
+* The `elementType` attribute of the `@Plugin` annotation must be configured, if it belongs under a certain category of elements (appenders, layouts, etc.)
+* 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 following details:
+
+* Layout's `@Plugin` annotation sets `category` and `elementType` to `Node.CATEGORY` and link:../javadoc/log4j-core/org/apache/logging/log4j/core/Layout.html#ELEMENT_TYPE[`Layout.ELEMENT_TYPE`], respectively
+* All plugin declarations are provided with a `@PluginBuilderFactory`-annotated static method
+* ``EventTemplateAdditionalField`` class' `@Plugin` annotation doesn't have an `elementType` attribute, even though it maps to a configuration file element
+
+[#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`
-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 plu [...]
+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.
-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.
+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.
-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 [...]
+[[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.
-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 proce [...]
+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.
-[source,xml]
+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`.
+
+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 xref:#PluginElement[the `@PluginElement` annotation]; now, any type supported by ``TypeConverter``s can be used in a `@PluginAttribute`-annotated factory attribute.
++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>
diff --cc src/site/resources/.htaccess
index a96bb00fa1,ce7adc4556..bacc9bc0fc
--- a/src/site/resources/.htaccess
+++ b/src/site/resources/.htaccess
@@@ -33,33 -33,20 +33,24 @@@ RewriteRule "^(.+)$" "$1.html
# The content moved between pages
RewriteRule "^articles\.html$" "manual/index.html" [R=permanent]
+ RewriteRule "^log4j-1\.2-api(/index)?\.html$" "manual/migration.html" [R=permanent]
RewriteRule "^log4j-api/apidocs(.*)$" "javadoc/log4j-api$1" [R=permanent]
- RewriteRule "^log4j-api/index\.html$" "manual/api.html" [R=permanent]
- RewriteRule "^log4j-api\.html$" "manual/api.html" [R=permanent]
+ RewriteRule "^log4j-api(/index)?\.html$" "manual/api.html" [R=permanent]
RewriteRule "^log4j-core/apidocs(.*)$" "javadoc/log4j-core$1" [R=permanent]
- RewriteRule "^log4j-jcl/index\.html$" "manual/installation.html#impl-core-bridge-jcl" [R=permanent,NE]
- RewriteRule "^log4j-jcl\.html$" "manual/installation.html#impl-core-bridge-jcl" [R=permanent,NE]
- RewriteRule "^log4j-jmx-gui/index\.html$" "/log4j/jmx-gui/latest/index.html" [R=permanent]
- RewriteRule "^log4j-jmx-gui\.html$" "/log4j/jmx-gui/latest/index.html" [R=permanent]
- RewriteRule "^log4j-jpl/index\.html$" "manual/installation.html#impl-core-bridge-jpl" [R=permanent,NE]
- RewriteRule "^log4j-jpl\.html$" "manual/installation.html#impl-core-bridge-jpl" [R=permanent,NE]
- RewriteRule "^log4j-jul/index\.html$" "manual/installation.html#impl-core-bridge-jul" [R=permanent,NE]
- RewriteRule "^log4j-jul\.html$" "manual/installation.html#impl-core-bridge-jul" [R=permanent,NE]
- RewriteRule "^log4j-mongodb3\.html$" "manual/appenders.html#NoSQLAppenderMongoDB" [R=permanent,NE]
- RewriteRule "^log4j-mongodb3/index\.html$" "manual/appenders.html#NoSQLAppenderMongoDB" [R=permanent,NE]
- RewriteRule "^log4j-mongodb4\.html$" "manual/appenders.html#log4j-mongodb4" [R=permanent,NE]
- RewriteRule "^log4j-mongodb4/index\.html$" "manual/appenders.html#log4j-mongodb4" [R=permanent,NE]
- RewriteRule "^log4j-slf4j-impl/index\.html$" "manual/installation.html#impl-core-bridge-slf4j" [R=permanent,NE]
- RewriteRule "^log4j-slf4j-impl\.html$" "manual/installation.html#impl-core-bridge-slf4j" [R=permanent,NE]
- RewriteRule "^log4j-slf4j2-impl/index\.html$" "manual/installation.html#impl-core-bridge-slf4j" [R=permanent,NE]
- RewriteRule "^log4j-slf4j2-impl\.html$" "manual/installation.html#impl-core-bridge-slf4j" [R=permanent,NE]
+ RewriteRule "^log4j-jcl(/index)?\.html$" "manual/installation.html#impl-core-bridge-jcl" [R=permanent,NE]
+ RewriteRule "^log4j-jmx-gui(/index)?\.html$" "/log4j/jmx-gui/latest/index.html" [R=permanent]
+ RewriteRule "^log4j-jpl(/index)?\.html$" "manual/installation.html#impl-core-bridge-jpl" [R=permanent,NE]
+ RewriteRule "^log4j-jul(/index)?\.html$" "manual/installation.html#impl-core-bridge-jul" [R=permanent,NE]
+ RewriteRule "^log4j-mongodb3(/index)?\.html$" "manual/appenders.html#NoSQLAppenderMongoDB" [R=permanent,NE]
+ 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#Appenders$" "manual/appenders.html#extending" [R=permanent]
+RewriteRule "^manual/extending\.html#Filters$" "manual/filters.html#extending" [R=permanent]
RewriteRule "^manual/extending\.html#Layouts$" "manual/layouts.html#extending" [R=permanent]
+RewriteRule "^manual/extending\.html#Lookups$" "manual/lookups.html#extending" [R=permanent]
RewriteRule "^manual/extending\.html#PatternConverters$" "manual/pattern-layout.html#extending-converters" [R=permanent]
+RewriteRule "^manual/extending\.html#Plugin_Builders$" "manual/plugins.html#declare-plugin-factory" [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]
(logging-log4j2) 01/07: Move extending appenders/filters/lookups to their own pages
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit f9deaaf961726256099e0449af8d33544a2b0a77
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Tue Jun 11 10:30:06 2024 +0200
Move extending appenders/filters/lookups to their own pages
---
.../modules/ROOT/pages/manual/appenders.adoc | 166 +++++++++++++-------
.../modules/ROOT/pages/manual/extending.adoc | 170 ---------------------
.../antora/modules/ROOT/pages/manual/filters.adoc | 66 ++++++--
.../antora/modules/ROOT/pages/manual/lookups.adoc | 83 +++++++---
src/site/resources/.htaccess | 3 +
5 files changed, 225 insertions(+), 263 deletions(-)
diff --git a/src/site/antora/modules/ROOT/pages/manual/appenders.adoc b/src/site/antora/modules/ROOT/pages/manual/appenders.adoc
index aad5a661a3..be44a32d4d 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
@@ -70,8 +70,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`.
@@ -1251,7 +1257,7 @@ table based on a Log4j `MapMessage` instead of values from `LogEvent`.
</Configuration>
----
-== JMS Appender
+=== JMS Appender
The JMS Appender sends the formatted log event to a JMS Destination.
@@ -1384,7 +1390,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`.
@@ -1562,7 +1568,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.
@@ -1636,7 +1642,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.
@@ -1721,7 +1727,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._
@@ -1816,7 +1822,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.
@@ -1907,10 +1913,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]
@@ -1980,7 +1986,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
link:#NoSQLAppender[NoSQLAppender] provider for MongoDB using the current MongoDB driver (version 5).
@@ -2069,7 +2075,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 link:#log4j-mongodb[NoSQL provider for MongoDB].
@@ -2159,7 +2165,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 link:#NoSQLAppender[NoSQLAppender] provider for CouchDB.
The NoSQLAppender writes log events to a NoSQL database using an internal lightweight provider interface.
@@ -2222,7 +2228,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.
@@ -2230,7 +2236,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
link:#FileAppender[FileAppender] except it is always buffered (this cannot be switched off) and internally it uses a
@@ -2310,7 +2316,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.
@@ -2342,13 +2348,13 @@ Appender in a link:#FailoverAppender[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.
@@ -2384,7 +2390,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.
@@ -2423,7 +2429,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.
@@ -2466,7 +2472,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`
@@ -2602,9 +2608,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
@@ -2621,7 +2627,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.
@@ -2642,7 +2648,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.
@@ -2661,7 +2667,7 @@ When running in Google App Engine, the OnStartup policy causes a rollover if the
`java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()`
and falls back to Log4J initialization time instead.)
-=== 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 @@ When combined with a time-based triggering policy the file pattern must contain
Otherwise, the target file will be overwritten on every rollover as the SizeBased Triggering Policy will not cause the timestamp value in the file name to change.
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
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
@@ -3046,7 +3052,7 @@ and must return a list with the paths to delete.
|=======================================================================
[#DeleteIfFileName]
-== DeleteIfFileName
+=== DeleteIfFileName
.IfFileName Condition Parameters
[cols="20%,20%,60%",options="header",]
@@ -3072,7 +3078,7 @@ the path name matches).
|=======================================================================
[#DeleteIfLastModified]
-== DeleteIfLastModified
+=== DeleteIfLastModified
.IfLastModified Condition Parameters
[cols="20%,20%,60%",options="header",]
@@ -3091,7 +3097,7 @@ the file is old enough).
|=======================================================================
[#DeleteIfAccumulatedFileCount]
-== DeleteIfAccumulatedFileCount
+=== DeleteIfAccumulatedFileCount
.IfAccumulatedFileCount Condition Parameters
[cols="20%,20%,60%",options="header",]
@@ -3108,7 +3114,7 @@ the threshold count has been exceeded).
|=======================================================================
[#DeleteIfAccumulatedFileSize]
-== DeleteIfAccumulatedFileSize
+=== DeleteIfAccumulatedFileSize
.IfAccumulatedFileSize Condition Parameters
[cols="20%,20%,60%",options="header",]
@@ -3202,7 +3208,7 @@ During every rollover, this configuration will delete files that match "*/app-*.
----
[#ScriptCondition]
-== ScriptCondition
+=== ScriptCondition
.ScriptCondition Parameters
[cols="20%,20%,60%",options="header",]
@@ -3217,7 +3223,7 @@ how ScriptFiles and ScriptRefs can be configured.
|=======================================================================
[#ScriptParameters]
-== ScriptParameters
+=== ScriptParameters
.Script Parameters
[cols="20%,20%,60%",options="header",]
@@ -3307,7 +3313,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
@@ -3399,7 +3405,7 @@ Below is a sample configuration that uses a RollingFileAppender and defines diff
----
[#RollingRandomAccessFileAppender]
-== RollingRandomAccessFileAppender
+=== RollingRandomAccessFileAppender
The RollingRandomAccessFileAppender is similar to the standard
link:#RollingFileAppender[RollingFileAppender] except it is always buffered (this cannot be switched off) and internally it uses a
@@ -3511,11 +3517,11 @@ file attribute view.
|=======================================================================
-=== Triggering Policies
+==== Triggering Policies
See xref:#TriggeringPolicies[RollingFileAppender Triggering Policies].
-=== Rollover Strategies
+==== Rollover Strategies
See link:#RolloverStrategies[RollingFileAppender Rollover Strategies].
@@ -3599,7 +3605,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.
@@ -3678,7 +3684,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`.
@@ -3763,7 +3769,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.
@@ -3807,7 +3813,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.
@@ -3916,7 +3922,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
@@ -3952,7 +3958,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.
@@ -4062,7 +4068,7 @@ This is a secured link:#SSL[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.
@@ -4085,7 +4091,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.
@@ -4118,7 +4124,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.
@@ -4154,7 +4160,7 @@ algorithms].
|=======================================================================
[#Example]
-=== Example
+==== Example
[source,xml]
----
@@ -4165,7 +4171,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.
@@ -4331,7 +4337,7 @@ For link:#SSL[SSL] this appender writes its output to a remote destination speci
----
[[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.
@@ -4462,3 +4468,45 @@ 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`]
+* The `elementType` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html#ELEMENT_TYPE[`Appender.ELEMENT_TYPE`]
+
+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 xref:#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`] – xref:#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`] – xref:#ConsoleAppender[Console Appender] writes log events to either `System.out` or `System.err` using `OutputStreamManager`
diff --git a/src/site/antora/modules/ROOT/pages/manual/extending.adoc b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
index b8d6395681..6b3e67233e 100644
--- a/src/site/antora/modules/ROOT/pages/manual/extending.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
@@ -208,176 +208,6 @@ a separate `FlowMessageFactory`. Applications may replace the
`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
diff --git a/src/site/antora/modules/ROOT/pages/manual/filters.adoc b/src/site/antora/modules/ROOT/pages/manual/filters.adoc
index baea1d507b..88e10b79ac 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
@@ -85,8 +86,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.
@@ -148,7 +155,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.
@@ -194,7 +201,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.
@@ -262,7 +269,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.
@@ -311,7 +318,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.
@@ -431,7 +438,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.
@@ -481,7 +488,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.
@@ -555,7 +562,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.
@@ -601,7 +608,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.
@@ -771,7 +778,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.
@@ -836,7 +843,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.
@@ -928,7 +935,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.
@@ -980,7 +987,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.
@@ -1037,3 +1044,36 @@ 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 xref:#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`]
+* The `elementType` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/Filter.html#ELEMENT_TYPE[`Filter.ELEMENT_TYPE`]
+
+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`] – xref:#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`] – xref:#RegexFilter[] matching on the message associated with the effective `LogEvent` in the context
diff --git a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
index 6eea0d2afe..33e9749801 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/8/docs/api/java/lang/management/RuntimeMXBean.htm
*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.
@@ -469,7 +477,7 @@ page for information on how to set the default values.
</Routing>
----
-== Marker Lookup
+=== Marker Lookup
The marker lookup allows you to use markers in interesting
configurations like a routing appender. Consider the following YAML
@@ -538,7 +546,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]
@@ -550,7 +559,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.
@@ -567,7 +577,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
@@ -596,7 +606,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
@@ -623,7 +633,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.
@@ -638,7 +648,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
@@ -698,3 +708,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 xref:#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`] – xref:#LowerLookup[] lower-cases its input
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/EventLookup.java[`EventLookup.java`] – xref:#EventLookup[] extracts specified fields from the effective `LogEvent` in the context
diff --git a/src/site/resources/.htaccess b/src/site/resources/.htaccess
index 708c2c5df7..6bef5ba191 100644
--- a/src/site/resources/.htaccess
+++ b/src/site/resources/.htaccess
@@ -54,7 +54,10 @@ RewriteRule "^log4j-slf4j-impl\.html$" "manual/installation.html#impl-core-bridg
RewriteRule "^log4j-slf4j2-impl/index\.html$" "manual/installation.html#impl-core-bridge-slf4j" [R=permanent,NE]
RewriteRule "^log4j-slf4j2-impl\.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#Appenders$" "manual/appenders.html#extending" [R=permanent]
+RewriteRule "^manual/extending\.html#Filters$" "manual/filters.html#extending" [R=permanent]
RewriteRule "^manual/extending\.html#Layouts$" "manual/layouts.html#extending" [R=permanent]
+RewriteRule "^manual/extending\.html#Lookups$" "manual/lookups.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]
(logging-log4j2) 03/07: Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 3c20113feaf48bb3eacb7da12f44edb4e818fcd7
Merge: 08d942ba74 ab70d4864f
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Tue Jun 11 20:11:29 2024 +0200
Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
.github/workflows/deploy-site.yaml | 13 +-
.mvn/develocity.xml | 1 +
.mvn/extensions.xml | 2 +-
.mvn/wrapper/maven-wrapper.properties | 10 +-
.../filter/HttpThreadContextMapFilterTest.java | 10 +-
.../core/selector/ClassLoaderContextSelector.java | 6 +-
log4j-parent/pom.xml | 2 +-
mvnw | 325 ++++++++++---------
mvnw.cmd | 37 ++-
...pdate_co_elastic_clients_elasticsearch_java.xml | 4 +-
...date_com_gradle_develocity_maven_extension.xml} | 4 +-
...tableExample.java => CustomMessageExample.java} | 11 +-
src/site/antora/modules/ROOT/pages/manual/api.adoc | 2 +
.../antora/modules/ROOT/pages/manual/messages.adoc | 292 ++++++++---------
.../modules/ROOT/pages/manual/pattern-layout.adoc | 346 +++++++++++----------
.../modules/ROOT/partials/manual/log-event.adoc | 61 ++++
16 files changed, 625 insertions(+), 501 deletions(-)
(logging-log4j2) 06/07: Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit fc1953b8452254f608e63ba73f7078613b8a78d5
Merge: 65b9924f21 26cc544418
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Thu Jun 20 09:53:30 2024 +0200
Merge remote-tracking branch 'origin/2.x' into doc/2.x/extending
.github/workflows/build.yaml | 5 +-
.github/workflows/deploy-site.yaml | 2 +-
.github/workflows/labeler.yaml | 8 +-
.github/workflows/merge-dependabot.yaml | 1 +
antora-playbook.yaml | 3 +
log4j-1.2-api/pom.xml | 11 -
.../java/org/apache/logging/log4j/EventLogger.java | 5 +-
log4j-core-test/pom.xml | 11 -
.../logging/log4j/core/layout/XmlLayoutTest.java | 4 +-
log4j-jul/pom.xml | 3 +
.../resources/threadLocalRecyclerNestedLogging.xml | 4 +-
.../json/resolver/TemplateResolverContext.java | 2 +-
.../TemplateResolverStringSubstitutor.java | 4 +-
.../template/json/resolver/package-info.java | 2 +-
log4j-osgi-test/pom.xml | 53 +++-
log4j-parent/pom.xml | 12 +-
pom.xml | 37 +++
...cate_duration.xml => deprecate_EventLogger.xml} | 4 +-
src/changelog/.2.x.x/deprecate_duration.xml | 4 +-
.../deprecate_log4j2_default_status_level.xml | 2 +-
src/changelog/.2.x.x/deprecate_log4j_mongodb4.xml | 4 +-
...pdate_co_elastic_clients_elasticsearch_java.xml | 4 +-
.../.2.x.x/update_org_apache_maven_maven_core.xml | 4 +-
...org_apache_maven_surefire_surefire_junit47.xml} | 4 +-
...te_org_springframework_spring_framework_bom.xml | 4 +-
src/site/antora/antora.tmpl.yml | 2 +
src/site/antora/antora.yml | 4 +-
.../ROOT/examples/manual/flowtracing/log4j2.json | 43 +++
.../{markers => flowtracing}/log4j2.properties | 32 ++-
.../manual/{markers => flowtracing}/log4j2.xml | 27 +-
.../manual/{markers => flowtracing}/log4j2.yaml | 30 +-
.../ROOT/examples/manual/flowtracing/logback.xml | 78 ++++++
.../log4j2.json | 0
.../log4j2.properties | 0
.../log4j2.xml | 0
.../log4j2.yaml | 0
.../property-substitution/log4j2.json | 27 ++
.../property-substitution}/log4j2.properties | 25 +-
.../log4j2.xml | 17 +-
.../log4j2.yaml | 14 +-
.../ROOT/examples/manual/markers/log4j2.json | 17 +-
.../ROOT/examples/manual/markers/log4j2.properties | 20 +-
.../ROOT/examples/manual/markers/log4j2.xml | 14 +-
.../ROOT/examples/manual/markers/log4j2.yaml | 11 +-
.../ROOT/examples/manual/markers/logback.xml | 41 ++-
src/site/antora/modules/ROOT/nav.adoc | 4 +-
src/site/antora/modules/ROOT/pages/faq.adoc | 2 +-
src/site/antora/modules/ROOT/pages/manual/api.adoc | 11 +-
.../modules/ROOT/pages/manual/appenders.adoc | 2 +-
.../modules/ROOT/pages/manual/architecture.adoc | 4 +-
.../antora/modules/ROOT/pages/manual/async.adoc | 2 +-
.../modules/ROOT/pages/manual/config-intro.adoc | 33 +++
.../modules/ROOT/pages/manual/configuration.adoc | 105 +++----
.../modules/ROOT/pages/manual/eventlogging.adoc | 242 ++--------------
.../antora/modules/ROOT/pages/manual/filters.adoc | 2 +-
.../modules/ROOT/pages/manual/flowtracing.adoc | 305 ++++++++++++---------
.../modules/ROOT/pages/manual/garbagefree.adoc | 2 +-
.../modules/ROOT/pages/manual/getting-started.adoc | 4 +-
.../modules/ROOT/pages/manual/installation.adoc | 11 +-
.../ROOT/pages/manual/json-template-layout.adoc | 153 +++++++++--
.../antora/modules/ROOT/pages/manual/layouts.adoc | 19 +-
.../antora/modules/ROOT/pages/manual/lookups.adoc | 1 +
.../antora/modules/ROOT/pages/manual/markers.adoc | 86 ++++--
.../antora/modules/ROOT/pages/manual/messages.adoc | 165 +++++++----
.../modules/ROOT/pages/manual/pattern-layout.adoc | 56 +++-
.../ROOT/pages/manual/systemproperties.adoc | 2 +-
.../modules/ROOT/pages/migrate-from-logback.adoc | 5 +-
.../modules/ROOT/pages/migrate-from-slf4j.adoc | 12 +-
.../antora/modules/ROOT/partials/concepts.adoc | 6 +-
.../ROOT/partials/manual/async-trade-offs.adoc | 2 +-
...-gcfree-lookup.adoc => structured-logging.adoc} | 8 +-
.../properties-log4j-core-misc.adoc | 2 +
72 files changed, 1066 insertions(+), 779 deletions(-)
diff --cc src/site/antora/modules/ROOT/pages/manual/lookups.adoc
index 41c17fd577,b417b5cd9e..86fbe88923
--- a/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/lookups.adoc
@@@ -477,7 -469,8 +477,8 @@@ page for information on how to set the
</Routing>
----
+ [#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
(logging-log4j2) 07/07: Revamp `extending.adoc`
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit e5b8161b0860858b6794e4cd998d05e2479a17c1
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Fri Jun 21 17:30:47 2024 +0200
Revamp `extending.adoc`
---
src/site/antora/modules/ROOT/pages/manual/api.adoc | 5 +
.../modules/ROOT/pages/manual/architecture.adoc | 14 +-
.../modules/ROOT/pages/manual/extending.adoc | 294 ++++++++-------------
.../antora/modules/ROOT/pages/manual/plugins.adoc | 14 +-
4 files changed, 133 insertions(+), 194 deletions(-)
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/architecture.adoc b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
index 448b392573..f151b79081 100644
--- a/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/architecture.adoc
@@ -84,14 +84,15 @@ 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].
+[#logger-context]
=== 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.
+The link:../javadoc/log4j-api/org/apache/logging/log4j/spi/LoggerContext.html[`LoggerContext`] acts as the anchor point for the logging system.
+It is primarily responsible for instantiating <<logger>>s.
+
+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
@@ -103,6 +104,7 @@ 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]
=== Logger
As stated previously, Loggers are created by calling
diff --git a/src/site/antora/modules/ROOT/pages/manual/extending.adoc b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
index 00c05df047..679aabb23b 100644
--- a/src/site/antora/modules/ROOT/pages/manual/extending.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
@@ -14,202 +14,132 @@
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#logger-context[`LoggerContext`]s.
+If you are using Log4j Core, you can provide a custom implementation using xref:manual/systemproperties.adoc#log4j2.loggerContextFactory[the `log4j2.loggerContextFactory` property].
+Another way to provide a custom `LoggerContextFactory` is to <<Provider,provide a custom `Provider`>>.
+But this is generally discouraged, since it requires a more complicated setup and is intended mostly to be used by Log4j API implementations.
[#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#logger-context[`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`
-[#LogEventFactory]
-== LogEventFactory
+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 suffice following conditions:
-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.
+* 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`]
-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.
+For example, see `RootLogger` definition in {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java[`LoggerConfig.java`].
-[#MessageFactory]
-== MessageFactory
+[#LogEventFactory]
+=== `LogEventFactory`
-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.
+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].
-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.
+[NOTE]
+====
+xref:manual/async.adoc[] discard `LogEventFactory` and any configuration related with it.
+====
-[#Custom_Plugins]
-== Custom Plugins
+[#MessageFactory]
+=== `MessageFactory2`
+
+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].
-// TODO
-See the xref:manual/plugins.adoc[Plugins] section of the manual.
+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].
diff --git a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
index f8beb69933..67dad5c9f2 100644
--- a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
@@ -47,18 +47,20 @@ In this section we will give an overview of the Log4j plugin system by answering
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`::
-Denotes the name of the plugin and is recommended to be distinct among plugins sharing the same `category`.
+Name of the plugin.
+It is recommended to be distinct among plugins sharing the same `category`.
`name` matching is case-insensitive.
-`category`::
+`category` (optional)::
A name used for grouping a set of plugins.
-`name` matching is case-sensitive.
+`category` matching is case-sensitive.
-`elementType`::
+`elementType` (optional)::
Name of the corresponding category of the xref:manual/configuration.adoc[Log4j configuration] file element this plugin belongs under.
You can omit this attribute if your plugin is not meant to be represented in a configuration file.
-For example, xref:manual/lookups.adoc#extending[lookups] only use the `category` attribute and set it to link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html#CATEGORY[`StrLookup.CATEGORY`] (`Lookup`).
+We will try to explain when to use `category` and `elementType` attributes with an example.
+xref:manual/lookups.adoc#extending[Lookups] only use the `category` attribute and set it to link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html#CATEGORY[`StrLookup.CATEGORY`] (`Lookup`).
On the other hand, xref:manual/appenders.adoc#extending[appenders] use both the `category` and `elementType` attributes and set them to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`] (`Core`) and link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html#ELEMENT_TYPE[`Appender.ELEMENT_TYPE`] (`appender`), respectively.
The reason appenders use an `elementType` and lookups don't is that appenders need to be referred to in an element in a Log4j configuration file (e.g., `log4j2.xml`) whereas lookups don't.
See <<core>> for details.
@@ -160,7 +162,7 @@ Each attribute or element annotation must include the name that must be present
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
+==== 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.
(logging-log4j2) 04/07: Rewrite `plugins.adoc`
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit d495947f48895810b6be8788f85f859333ce2226
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Wed Jun 12 11:03:58 2024 +0200
Rewrite `plugins.adoc`
---
.../modules/ROOT/pages/manual/extending.adoc | 119 ---------
.../antora/modules/ROOT/pages/manual/plugins.adoc | 278 +++++++++++++++++----
src/site/resources/.htaccess | 3 +
3 files changed, 234 insertions(+), 166 deletions(-)
diff --git a/src/site/antora/modules/ROOT/pages/manual/extending.adoc b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
index 6b3e67233e..4ce2ac3333 100644
--- a/src/site/antora/modules/ROOT/pages/manual/extending.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/extending.adoc
@@ -208,125 +208,6 @@ a separate `FlowMessageFactory`. Applications may replace the
`log4j2.flowMessageFactory` to the name of the custom `FlowMessageFactory`
class.
-[#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();
-----
-
[#Custom_Plugins]
== Custom Plugins
diff --git a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
index c793d404c4..cbca9ff4ec 100644
--- a/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/plugins.adoc
@@ -14,39 +14,227 @@
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`::
+Denotes the name of the plugin and is recommended to be distinct among plugins sharing the same `category`.
+`name` matching is case-insensitive.
+
+`category`::
+A name used for grouping a set of plugins.
+`name` matching is case-sensitive.
+
+`elementType`::
+Name of the corresponding category of the xref:manual/configuration.adoc[Log4j configuration] file element this plugin belongs under.
+You can omit this attribute if your plugin is not meant to be represented in a configuration file.
+
+For example, xref:manual/lookups.adoc#extending[lookups] only use the `category` attribute and set it to link:../javadoc/log4j-core/org/apache/logging/log4j/core/lookup/StrLookup.html#CATEGORY[`StrLookup.CATEGORY`] (`Lookup`).
+On the other hand, xref:manual/appenders.adoc#extending[appenders] use both the `category` and `elementType` attributes and set them to link:../javadoc/log4j-core/org/apache/logging/log4j/core/config/Node.html#CATEGORY[`Node.CATEGORY`] (`Core`) and link:../javadoc/log4j-core/org/apache/logging/log4j/core/Appender.html#ELEMENT_TYPE[`Appender.ELEMENT_TYPE`] (`appender`), respectively.
+The reason appenders use an `elementType` and lookups don't is that appenders need to be referred to in an element in a Log4j configuration file (e.g., `log4j2.xml`) whereas lookups don't.
+See <<core>> for details.
+
+For clarity's sake, see following examples:
+
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/DateLookup.java[`LowerLookup.java`] (uses only `category`)
+* {project-github-url}/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java[`CsvParameterLayout.java`] (uses both `category` and `elementType`)
+
+.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`)
+* The `elementType` attribute of the `@Plugin` annotation must be configured, if it belongs under a certain category of elements (appenders, layouts, etc.)
+* 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 following details:
+
+* Layout's `@Plugin` annotation sets `category` and `elementType` to `Node.CATEGORY` and link:../javadoc/log4j-core/org/apache/logging/log4j/core/Layout.html#ELEMENT_TYPE[`Layout.ELEMENT_TYPE`], respectively
+* All plugin declarations are provided with a `@PluginBuilderFactory`-annotated static method
+* ``EventTemplateAdditionalField`` class' `@Plugin` annotation doesn't have an `elementType` attribute, even though it maps to a configuration file element
+
+[#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`
-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/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.
-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.
+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.
-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 [...]
+[[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.
-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/PluginNode.html[`@PluginNode`]::
+The current `Node` being parsed will be passed to the plugin as a parameter.
-[source,xml]
+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`.
+
+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 xref:#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 +242,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.
+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/resources/.htaccess b/src/site/resources/.htaccess
index 6bef5ba191..a96bb00fa1 100644
--- a/src/site/resources/.htaccess
+++ b/src/site/resources/.htaccess
@@ -59,6 +59,7 @@ RewriteRule "^manual/extending\.html#Filters$" "manual/filters.html#extending" [
RewriteRule "^manual/extending\.html#Layouts$" "manual/layouts.html#extending" [R=permanent]
RewriteRule "^manual/extending\.html#Lookups$" "manual/lookups.html#extending" [R=permanent]
RewriteRule "^manual/extending\.html#PatternConverters$" "manual/pattern-layout.html#extending-converters" [R=permanent]
+RewriteRule "^manual/extending\.html#Plugin_Builders$" "manual/plugins.html#declare-plugin-factory" [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]
@@ -98,6 +99,8 @@ RewriteRule "^manual/layouts\.html#Process_ID$" "manual/pattern-layout.html#conv
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/plugins\.html#developer-notes$" "manual/plugins.html" [R=permanent]
+RewriteRule "^manual/plugins\.html#lookups$" "manual/lookups.html#extending" [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]
(logging-log4j2) 02/07: Improve extending layouts
Posted by vy...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vy pushed a commit to branch doc/2.x/extending
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 08d942ba7497a57ca5abac461c83d91c1e995d4a
Author: Volkan Yazıcı <vo...@yazi.ci>
AuthorDate: Tue Jun 11 10:30:22 2024 +0200
Improve extending layouts
---
src/site/antora/modules/ROOT/pages/manual/layouts.adoc | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
index ec12ec8ee3..8c376c290c 100644
--- a/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
+++ b/src/site/antora/modules/ROOT/pages/manual/layouts.adoc
@@ -1100,6 +1100,12 @@ 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`]
+* The `elementType` attribute is set to link:../javadoc/log4j-core/org/apache/logging/log4j/core/Layout.html#ELEMENT_TYPE[`Layout.ELEMENT_TYPE`]
+
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`