blob: d67ed68a84c10ce2281b615f2b68cd27d32f9dd5 [file] [log] [blame]
////
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
////
= Plugins
Ralph Goers <rgoers@apache.org>; Matt Sicker <mattsicker@apache.org>
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.
In Log4j 2 a plugin is declared by adding a
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/plugins/Plugin.html[`@Plugin`]
annotation to the class declaration. During initialization the
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/Configuration.html[`Configuration`]
will invoke the
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/plugins/util/PluginManager.html[`PluginManager`]
to load the built-in Log4j plugins as well as any custom plugins. The
`PluginManager` locates plugins by looking in five places:
1. Plugin collection classes on the classpath that are loaded by java.util.ServiceLoader.
These classes 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-plugins` has started. Bundles must register their plugin collection
class as an OSGi service.
3. A comma-separated list of packages specified by the
`log4j.plugin.packages` system property.
4. Packages passed to the static `PluginManager.addPackages` method
(before Log4j configuration occurs).
5. The link:./configuration.html#ConfigurationSyntax[packages] declared
in your log4j2 configuration file.
6. Serialized plugin listing files on the classpath. These files were generated by
the plugin annotation processor in Log4j 2 2.x. These are processed to allow
compatibility.
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 follows the same order that bundles were installed into the
framework. See
http://www.osgi.org/javadoc/r5/core/org/osgi/framework/BundleContext.html#getBundles()[`getBundles()`]
and
http://www.osgi.org/javadoc/r5/core/org/osgi/framework/SynchronousBundleListener.html[`SynchronousBundleListener`].
In short, name collisions are even more unpredictable in an OSGi environment.
////
TODO: in future, plugins will be able to be annotated with @Order which can override priorities
////
Plugin collection classes are generated by an annotation processor contained
in the log4j-plugins artifact which will automatically scan your code for
Log4j 2 plugins and generate a Java source file that references all the
located plugins. It will also generate a
META-INF/services/org.apache.logging.log4j.plugins.processor.PluginService
file in compliance with java.util.ServiceLoader.
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.
If annotation processing is disabled plugins may still be registered by either
[loweralpha]
.. manually providing a class that extends `org.apache.logging.log4j.plugins.processor.PluginService`
and identifies all the plugins and also declaring a
`META-INF/services/org.apache.logging.log4j.plugins.processor.PluginService` file
that provides the fully qualified name of the implemented class or
.. adding another compiler pass to the build process that
only handles annotation processing using the Log4j 2 annotation
processor class,
`org.apache.logging.log4j.plugins.processor.PluginProcessor`.
To do this using Apache Maven, add the following execution to your
_maven-compiler-plugin_ (version 2.2 or higher) build plugin:
[source,xml]
----
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<executions>
<execution>
<id>log4j-plugin-processor</id>
<goals>
<goal>compile</goal>
</goals>
<phase>process-classes</phase>
<configuration>
<proc>only</proc>
<annotationProcessors>
<annotationProcessor>org.apache.logging.log4j.plugins.processor.PluginProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</execution>
</executions>
</plugin>
----
As the configuration is processed the appropriate plugins will be
automatically configured and initialized.
Log4j 2 utilizes a few different categories of plugins which are described
in the following sections.
[#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.
Core plugins follow a few simple dependency injection rules for binding
`Configuration` parameters into a factory entry point. Each plugin must
declare a static method annotated with `@PluginFactory`.
This method can either list all options as method parameters, or it can return
a new `Builder<T>` instance where options are available as either single-argument
`setFoo` or `withFoo` methods or fields. There are a few different attribute types
available to denote `Configuration` data that are injected by the plugin
framework. These are available as annotations that can either be used on the
method parameters to return an instance of the plugin, or they can be used on the
returned builder class's methods or fields. Each annotation may include the
name that must be present in the configuration in order to match the
configuration item to its respective parameter. If no name is specified, then
the name used is as follows:
* When annotated on a parameter, this will use the parameter name.
* When annotated on a single argument method, if the method name is prefixed by
`set` or `with`, this will use the remainder of the method name. Otherwise, the
full method name is used.
* When annotated on a field, this will used the field name.
There are dozens of plugins in Log4j Core that can be
used as examples for more complex scenarios including hierarchical
builder classes (e.g., see `FileAppender`). See
link:extending.html#Plugin_Builders[Extending Log4j with Plugin
Builders] for more details.
=== Attribute Types
link:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/PluginAttribute.html[`PluginAttribute`]::
The parameter must be convertible from a String using a
link:#TypeConverters[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.
link:../log4j-plugins/apidocs/org/apache/logging/log4j/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.
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/plugins/PluginConfiguration.html[`PluginConfiguration`]::
The current `Configuration` object will be passed to the plugin as a
parameter.
link:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/PluginNode.html[`PluginNode`]::
The current `Node` being parsed will be passed to the plugin as a
parameter.
link:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/PluginValue.html[`PluginValue`]::
The value of the current `Node` or its attribute named `value`.
=== Constraint Validators
Plugin factory fields, methods, and parameters can be automatically validated at
runtime using constraint validators inspired by the
http://beanvalidation.org/[Bean Validation spec]. The following
annotations are bundled in Log4j, but custom
link:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/validation/ConstraintValidator.html[`ConstraintValidators`]
can be created as well.
link:../log4j-plugins/apidocs/org/apache/logging/log4j/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:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/validation/constraints/ValidHost.html[`ValidHost`]::
This annotation validates that a value corresponds to a valid
hostname. This uses the same validation as
http://docs.oracle.com/javase/8/docs/api/java/net/InetAddress.html#getByName-java.lang.String-[`InetAddress::getByName`].
link:../log4j-core/apidocs/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.
[#Converters]
== Converters
Converters are used by
link:../log4j-core/apidocs/org/apache/logging/log4j/core/layout/PatternLayout.html[`PatternLayout`]
to render the elements identified by the conversion pattern. Every
converter must specify its category as "Converter" on the `@Plugin`
annotation, have a static `newInstance` method that accepts an array of
`String` as its only parameter and returns an instance of the
Converter, and must have a `@ConverterKeys` annotation present that
contains the array of converter patterns that will cause the Converter
to be selected. Converters that are meant to handle `LogEvent` must
extend the
link:../log4j-core/apidocs/org/apache/logging/log4j/core/layout/LogEventPatternConverter.html[`LogEventPatternConverter`]
class and must implement a format method that accepts a `LogEvent` and a
`StringBuilder` as arguments. The Converter should append the result of
its operation to the `StringBuilder`.
A second type of Converter is the FileConverter - which must have
"FileConverter" specified in the category attribute of the `@Plugin`
annotation. While similar to a `LogEventPatternConverter`, instead of a
single format method these Converters will have two variations; one that
takes an `Object` and one that takes an array of `Object` instead of
the `LogEvent`. Both append to the provided `StringBuilder` in the same
fashion as a `LogEventPatternConverter`. These Converters are typically
used by the `RollingFileAppender` to construct the name of the file to
log to.
If multiple Converters specify the same `ConverterKeys`, then the load
order above determines which one will be used. For example, to override
the `%date` converter which is provided by the built-in
`DatePatternConverter` class, you would need to place your plugin in a
JAR file in the CLASSPATH ahead of `log4j-core.jar`. This is not
recommended; pattern ConverterKeys collisions will cause a warning to be
emitted. Try to use unique ConverterKeys for your custom pattern
converters.
[#KeyProviders]
== KeyProviders
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
link:../log4j-core/apidocs/org/apache/logging/log4j/core/util/SecretKeyProvider.html[`SecretKeyProvider`]
interface.
[#Lookups]
== Lookups
Lookups are perhaps the simplest plugins of all. They must declare their
type as "Lookup" on the plugin annotation and must implement the
link:../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrLookup.html[`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 to
locate.
[#TypeConverters]
== TypeConverters
link:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/convert/TypeConverter.html[`TypeConverter`]s
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
link:../log4j-plugins/apidocs/org/apache/logging/log4j/plugins/convert/TypeConverters.html[`TypeConverters`]
and
link:../log4j-core/apidocs/org/apache/logging/log4j/core/config/plugins/convert/CoreConverters.html[`CoreConverters`]
for a more exhaustive listing.
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.
[#DeveloperNotes]
== Developer Notes
If a plugin class implements
http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html[`Collection`]
or http://docs.oracle.com/javase/6/docs/api/java/util/Map.html[`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`.