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ı <[email protected]> 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.
