| <!DOCTYPE html> |
| <!-- |
| | Generated by Apache Maven Doxia Site Renderer 1.9.1 from src/site/xdoc/manual/extending.xml at 2019-12-11 |
| | Rendered using Apache Maven Fluido Skin 1.8 |
| --> |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <meta name="generator" content="Apache Maven Doxia Site Renderer 1.9.1" /> |
| <meta name="author" content="Ralph Goers" /> |
| <title>Log4j – Extending Log4j 2</title> |
| <link rel="stylesheet" href="../css/apache-maven-fluido-1.8.min.css" /> |
| <link rel="stylesheet" href="../css/site.css" /> |
| <link rel="stylesheet" href="../css/print.css" media="print" /> |
| <script src="../js/apache-maven-fluido-1.8.min.js"></script> |
| </head> |
| <body class="topBarDisabled"> |
| <div class="container-fluid"> |
| <header> |
| <div id="banner"> |
| <div class="pull-left"><a href="http://logging.apache.org" id="bannerLeft"><img src="../images/ls-logo.jpg" alt=""/></a></div> |
| <div class="pull-right"><a href="http://logging.apache.org/log4j/2.x" id="bannerRight"><img src="../images/logo.png" alt=""/></a></div> |
| <div class="clear"><hr/></div> |
| </div> |
| |
| <div id="breadcrumbs"> |
| <ul class="breadcrumb"> |
| <li id="publishDate">Last Published: 2019-12-11<span class="divider">|</span> |
| </li> |
| <li id="projectVersion">Version: 2.13.0</li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://github.com/apache/logging-log4j2" class="externalLink" title="GitHub">GitHub</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://analysis.apache.org/dashboard/index/org.apache.logging.log4j:log4j" class="externalLink" title="Sonar">Sonar</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="../../../" title="Logging Services">Logging Services</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://www.apache.org/" class="externalLink" title="Apache">Apache</a></li> |
| <li class="pull-right"><a href="https://cwiki.apache.org/confluence/display/LOGGING/Log4j" class="externalLink" title="Logging Wiki">Logging Wiki</a></li> |
| </ul> |
| </div> |
| </header> |
| <div class="row-fluid"> |
| <header id="leftColumn" class="span2"> |
| <nav class="well sidebar-nav"> |
| <ul class="nav nav-list"> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/home.png" alt="Apache Log4j™ 2" border="0"/> Apache Log4j™ 2</li> |
| <li><a href="../index.html" title="About"><span class="none"></span>About</a></li> |
| <li><a href="../download.html" title="Download"><span class="none"></span>Download</a></li> |
| <li><a href="../javadoc.html" title="Javadoc"><span class="icon-chevron-right"></span>Javadoc</a></li> |
| <li><a href="../maven-artifacts.html" title="Maven, Ivy, Gradle Artifacts"><span class="icon-chevron-right"></span>Maven, Ivy, Gradle Artifacts</a></li> |
| <li><a href="../runtime-dependencies.html" title="Runtime Dependencies"><span class="none"></span>Runtime Dependencies</a></li> |
| <li><a href="../changelog.html" title="Changelog"><span class="none"></span>Changelog</a></li> |
| <li><a href="../faq.html" title="FAQ"><span class="none"></span>FAQ</a></li> |
| <li><a href="../performance.html" title="Performance"><span class="icon-chevron-right"></span>Performance</a></li> |
| <li><a href="../articles.html" title="Articles and Tutorials"><span class="none"></span>Articles and Tutorials</a></li> |
| <li><a href="../thanks.html" title="Thanks"><span class="none"></span>Thanks</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/pencil.png" alt="For Contributors" border="0"/> For Contributors</li> |
| <li><a href="../build.html" title="Building Log4j from Source"><span class="none"></span>Building Log4j from Source</a></li> |
| <li><a href="../guidelines.html" title="Guidelines"><span class="none"></span>Guidelines</a></li> |
| <li><a href="../javastyle.html" title="Style Guide"><span class="none"></span>Style Guide</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/book.png" alt="Manual" border="0"/> Manual</li> |
| <li><a href="../manual/index.html" title="Introduction"><span class="none"></span>Introduction</a></li> |
| <li><a href="../manual/architecture.html" title="Architecture"><span class="none"></span>Architecture</a></li> |
| <li><a href="../manual/compatibility.html" title="Log4j 1.x Compatibility"><span class="none"></span>Log4j 1.x Compatibility</a></li> |
| <li><a href="../manual/migration.html" title="Log4j 1.x Migration"><span class="none"></span>Log4j 1.x Migration</a></li> |
| <li><a href="../manual/api.html" title="Java API"><span class="icon-chevron-right"></span>Java API</a></li> |
| <li><a href="../manual/scala-api.html" title="Scala API"><span class="none"></span>Scala API</a></li> |
| <li><a href="../manual/configuration.html" title="Configuration"><span class="icon-chevron-right"></span>Configuration</a></li> |
| <li><a href="../manual/usage.html" title="Usage"><span class="icon-chevron-right"></span>Usage</a></li> |
| <li><a href="../manual/webapp.html" title="Web Applications and JSPs"><span class="icon-chevron-right"></span>Web Applications and JSPs</a></li> |
| <li><a href="../manual/lookups.html" title="Lookups"><span class="icon-chevron-right"></span>Lookups</a></li> |
| <li><a href="../manual/appenders.html" title="Appenders"><span class="icon-chevron-right"></span>Appenders</a></li> |
| <li><a href="../manual/layouts.html" title="Layouts"><span class="icon-chevron-right"></span>Layouts</a></li> |
| <li><a href="../manual/filters.html" title="Filters"><span class="icon-chevron-right"></span>Filters</a></li> |
| <li><a href="../manual/async.html" title="Async Loggers"><span class="icon-chevron-right"></span>Async Loggers</a></li> |
| <li><a href="../manual/garbagefree.html" title="Garbage-free Logging"><span class="icon-chevron-right"></span>Garbage-free Logging</a></li> |
| <li><a href="../manual/jmx.html" title="JMX"><span class="none"></span>JMX</a></li> |
| <li><a href="../manual/logsep.html" title="Logging Separation"><span class="none"></span>Logging Separation</a></li> |
| <li class="active"><a href="#"><span class="icon-chevron-down"></span>Extending Log4j</a> |
| <ul class="nav nav-list"> |
| <li><a href="../manual/extending.html#LoggerContextFactory" title="LoggerContextFactory"><span class="none"></span>LoggerContextFactory</a></li> |
| <li><a href="../manual/extending.html#ContextSelector" title="ContextSelector"><span class="none"></span>ContextSelector</a></li> |
| <li><a href="../manual/extending.html#ConfigurationFactory" title="ConfigurationFactory"><span class="none"></span>ConfigurationFactory</a></li> |
| <li><a href="../manual/extending.html#LoggerConfig" title="LoggerConfig"><span class="none"></span>LoggerConfig</a></li> |
| <li><a href="../manual/extending.html#LogEventFactory" title="LogEventFactory"><span class="none"></span>LogEventFactory</a></li> |
| <li><a href="../manual/extending.html#MessageFactory" title="MessageFactory"><span class="none"></span>MessageFactory</a></li> |
| <li><a href="../manual/extending.html#Lookups" title="Lookups"><span class="none"></span>Lookups</a></li> |
| <li><a href="../manual/extending.html#Filters" title="Filters"><span class="none"></span>Filters</a></li> |
| <li><a href="../manual/extending.html#Appenders" title="Appenders"><span class="none"></span>Appenders</a></li> |
| <li><a href="../manual/extending.html#Layouts" title="Layouts"><span class="none"></span>Layouts</a></li> |
| <li><a href="../manual/extending.html#PatternConverters" title="PatternConverters"><span class="none"></span>PatternConverters</a></li> |
| <li><a href="../manual/extending.html#Plugin_Builders" title="Plugin Builders"><span class="none"></span>Plugin Builders</a></li> |
| <li><a href="../manual/extending.html#Custom_ContextDataInjector" title="Custom ContextDataInjector"><span class="none"></span>Custom ContextDataInjector</a></li> |
| <li><a href="../manual/extending.html#Custom_Plugins" title="Custom Plugins"><span class="none"></span>Custom Plugins</a></li> |
| </ul></li> |
| <li><a href="../manual/plugins.html" title="Plugins"><span class="icon-chevron-right"></span>Plugins</a></li> |
| <li><a href="../manual/customconfig.html" title="Programmatic Log4j Configuration"><span class="icon-chevron-right"></span>Programmatic Log4j Configuration</a></li> |
| <li><a href="../manual/customloglevels.html" title="Custom Log Levels"><span class="icon-chevron-right"></span>Custom Log Levels</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/tag.png" alt="Related Projects" border="0"/> Related Projects</li> |
| <li><a href="http://logging.apache.org/log4j/scala/index.html" class="externalLink" title="Log4j-Scala"><span class="none"></span>Log4j-Scala</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/link.png" alt="Legacy Sites" border="0"/> Legacy Sites</li> |
| <li><a href="http://logging.apache.org/log4j/1.2/" class="externalLink" title="Log4j 1.2 - End of Life"><span class="none"></span>Log4j 1.2 - End of Life</a></li> |
| <li><a href="http://logging.apache.org/log4j/log4j-2.3/" class="externalLink" title="Log4j 2.3 - Java 6"><span class="none"></span>Log4j 2.3 - Java 6</a></li> |
| <li><a href="http://logging.apache.org/log4j/log4j-2.12.1" class="externalLink" title="Log4j 2.12.1 - Java 7"><span class="none"></span>Log4j 2.12.1 - Java 7</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/cog.png" alt="Components" border="0"/> Components</li> |
| <li><a href="../log4j-api/index.html" title="API"><span class="none"></span>API</a></li> |
| <li><a href="../log4j-core/index.html" title="Implementation"><span class="none"></span>Implementation</a></li> |
| <li><a href="../log4j-jcl/index.html" title="Commons Logging Bridge"><span class="none"></span>Commons Logging Bridge</a></li> |
| <li><a href="../log4j-1.2-api/index.html" title="Log4j 1.2 API"><span class="none"></span>Log4j 1.2 API</a></li> |
| <li><a href="../log4j-slf4j-impl/index.html" title="SLF4J Binding"><span class="none"></span>SLF4J Binding</a></li> |
| <li><a href="../log4j-jul/index.html" title="JUL Adapter"><span class="none"></span>JUL Adapter</a></li> |
| <li><a href="../log4j-to-slf4j/index.html" title="Log4j 2 to SLF4J Adapter"><span class="none"></span>Log4j 2 to SLF4J Adapter</a></li> |
| <li><a href="../log4j-flume-ng/index.html" title="Apache Flume Appender"><span class="none"></span>Apache Flume Appender</a></li> |
| <li><a href="../log4j-taglib/index.html" title="Log4j Tag Library"><span class="none"></span>Log4j Tag Library</a></li> |
| <li><a href="../log4j-jmx-gui/index.html" title="Log4j JMX GUI"><span class="none"></span>Log4j JMX GUI</a></li> |
| <li><a href="../log4j-web/index.html" title="Log4j Web Application Support"><span class="none"></span>Log4j Web Application Support</a></li> |
| <li><a href="../log4j-appserver/index.html" title="Log4j Application Server Integration"><span class="none"></span>Log4j Application Server Integration</a></li> |
| <li><a href="../log4j-couchdb/index.html" title="Log4j CouchDB appender"><span class="none"></span>Log4j CouchDB appender</a></li> |
| <li><a href="../log4j-mongodb2/index.html" title="Log4j MongoDB2 appender"><span class="none"></span>Log4j MongoDB2 appender</a></li> |
| <li><a href="../log4j-mongodb3/index.html" title="Log4j MongoDB3 appender"><span class="none"></span>Log4j MongoDB3 appender</a></li> |
| <li><a href="../log4j-cassandra/index.html" title="Log4j Cassandra appender"><span class="none"></span>Log4j Cassandra appender</a></li> |
| <li><a href="../log4j-iostreams/index.html" title="Log4j IO Streams"><span class="none"></span>Log4j IO Streams</a></li> |
| <li><a href="../log4j-liquibase/index.html" title="Log4j Liquibase Binding"><span class="none"></span>Log4j Liquibase Binding</a></li> |
| <li><a href="../log4j-docker/index.html" title="Log4j Docker Support"><span class="none"></span>Log4j Docker Support</a></li> |
| <li><a href="../log4j-spring-cloud-config/log4j-spring-cloud-config-client/index.html" title="Log4j Spring Cloud Config Client"><span class="none"></span>Log4j Spring Cloud Config Client</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/info.png" alt="Project Information" border="0"/> Project Information</li> |
| <li><a href="../dependency-convergence.html" title="Dependency Convergence"><span class="none"></span>Dependency Convergence</a></li> |
| <li><a href="../dependency-management.html" title="Dependency Management"><span class="none"></span>Dependency Management</a></li> |
| <li><a href="../team-list.html" title="Project Team"><span class="none"></span>Project Team</a></li> |
| <li><a href="../mail-lists.html" title="Mailing Lists"><span class="none"></span>Mailing Lists</a></li> |
| <li><a href="../issue-tracking.html" title="Issue Tracking"><span class="none"></span>Issue Tracking</a></li> |
| <li><a href="../license.html" title="Project License"><span class="none"></span>Project License</a></li> |
| <li><a href="../source-repository.html" title="Source Repository"><span class="none"></span>Source Repository</a></li> |
| <li><a href="../project-summary.html" title="Project Summary"><span class="none"></span>Project Summary</a></li> |
| <li class="nav-header"><img class="imageLink" src="../img/glyphicons/layers.png" alt="Project Reports" border="0"/> Project Reports</li> |
| <li><a href="../changes-report.html" title="Changes Report"><span class="none"></span>Changes Report</a></li> |
| <li><a href="../jira-report.html" title="JIRA Report"><span class="none"></span>JIRA Report</a></li> |
| <li><a href="../rat-report.html" title="RAT Report"><span class="none"></span>RAT Report</a></li> |
| </ul> |
| </nav> |
| <div class="well sidebar-nav"> |
| <hr /> |
| <div id="poweredBy"> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" /></a> |
| </div> |
| </div> |
| </header> |
| <main id="bodyColumn" class="span10" > |
| |
| |
| <section> |
| <h2><a name="Extending_Log4j"></a>Extending Log4j</h2> |
| |
| <p> |
| Log4j 2 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 2 implementation. |
| </p> |
| <section> |
| <h3><a name="LoggerContextFactory"></a>LoggerContextFactory</h3> |
| |
| <p> |
| 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 extendsorg.apache.logging.log4j.spi.Provider and should have a |
| no-arg constructor that delegates to Provider's constructor passing the <var>Priority</var>, |
| 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 <var>Priority</var> 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. |
| </p> |
| |
| <p> |
| Applications may change the LoggerContextFactory that will be used by |
| </p> |
| |
| <ol style="list-style-type: decimal"> |
| |
| <li>Create a binding to the logging implementation. |
| |
| <ol style="list-style-type: lower-alpha"> |
| |
| <li>Implement a new LoggerContextFactory.</li> |
| |
| <li>Implement a class that extends org.apache.logging.spi.Provider. with a no-arg |
| constructor that calls super-class's constructor with the <var>Priority</var>, the API version(s), |
| LoggerContextFactory class, and optionally, a ThreadContextMap |
| implementation class.</li> |
| |
| <li>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. |
| </li> |
| </ol></li> |
| |
| <li>Setting the system property <var>log4j2.loggerContextFactory</var> to the name of the |
| LoggerContextFactory class to use. |
| </li> |
| |
| <li>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. |
| </li> |
| </ol> |
| </section> |
| <section> |
| <h3><a name="ContextSelector"></a>ContextSelector</h3> |
| |
| <p> |
| ContextSelectors are called by the |
| <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/impl/Log4jContextFactory.html">Log4j |
| LoggerContext factory</a>. 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 a System Property named "Log4jContextSelector". |
| If found, the property is expected to contain the name of the Class that implements the |
| ContextSelector to be used. |
| </p> |
| |
| <p> |
| Log4j provides five ContextSelectors: |
| </p> |
| |
| <dl> |
| |
| <dt><a href="../log4j-core/apidocs/org/apache/logging/log4j/core/selector/BasicContextSelector.html" class="javadoc">BasicContextSelector</a></dt> |
| |
| <dd>Uses either a LoggerContext that has been stored in a ThreadLocal or a common LoggerContext.</dd> |
| |
| <dt><a href="../log4j-core/apidocs/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.html" class="javadoc">ClassLoaderContextSelector</a></dt> |
| |
| <dd>Associates LoggerContexts with the ClassLoader that created the caller of the getLogger call. This is |
| the default ContextSelector.</dd> |
| |
| <dt><a href="../log4j-core/apidocs/org/apache/logging/log4j/core/selector/JndiContextSelector.html" class="javadoc">JndiContextSelector</a></dt> |
| |
| <dd>Locates the LoggerContext by querying JNDI.</dd> |
| |
| <dt><a href="../log4j-core/apidocs/org/apache/logging/log4j/core/async/AsyncLoggerContextSelector.html" class="javadoc">AsyncLoggerContextSelector</a></dt> |
| |
| <dd>Creates a LoggerContext that ensures that all loggers are AsyncLoggers.</dd> |
| |
| <dt><a href="../log4j-core/apidocs/org/apache/logging/log4j/core/osgi/BundleContextSelector.html" class="javadoc">BundleContextSelector</a></dt> |
| |
| <dd>Associates LoggerContexts with the ClassLoader of the bundle that created the caller of the getLogger |
| call. This is enabled by default in OSGi environments.</dd> |
| </dl> |
| </section> |
| <section> |
| <h3><a name="ConfigurationFactory"></a>ConfigurationFactory</h3> |
| |
| <p> |
| 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 |
| <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/config/ConfigurationFactory.html">ConfigurationFactory</a>. |
| 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. |
| </p> |
| |
| <p> |
| 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 Configuration object. |
| </p> |
| |
| <p> |
| Most Configuration extend the BaseConfiguration 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. BaseConfiguration will then be |
| passed the Node tree and instantiate the configuration objects from that. |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @Plugin(name = "XMLConfigurationFactory", category = "ConfigurationFactory") |
| @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; |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="LoggerConfig"></a>LoggerConfig</h3> |
| |
| <p> |
| LoggerConfig objects are where Loggers created by applications tie into the configuration. The Log4j |
| implementation requires that all LoggerConfigs be 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. |
| </p> |
| |
| <p> |
| The following example shows how the root LoggerConfig simply extends a generic LoggerConfig. |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @Plugin(name = "root", category = "Core", printObject = true) |
| public static class RootLogger extends LoggerConfig { |
| |
| @PluginFactory |
| public static LoggerConfig createLogger(@PluginAttribute(value = "additivity", defaultBooleanValue = true) boolean additivity, |
| @PluginAttribute(value = "level", defaultStringValue = "ERROR") Level level, |
| @PluginElement("AppenderRef") AppenderRef[] refs, |
| @PluginElement("Filters") Filter filter) { |
| List<AppenderRef> appenderRefs = Arrays.asList(refs); |
| return new LoggerConfig(LogManager.ROOT_LOGGER_NAME, appenderRefs, filter, level, additivity); |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="LogEventFactory"></a>LogEventFactory</h3> |
| |
| <p>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. </p> |
| |
| <p>Note: When log4j is configured to have <a href="async.html#AllAsync">all loggers asynchronous</a>, |
| log events are pre-allocated in a ring buffer and the LogEventFactory is not used.</p> |
| </section> |
| <section> |
| <h3><a name="MessageFactory"></a>MessageFactory</h3> |
| |
| <p>A MessageFactory is used to generate Message objects. Applications may replace the standard |
| ParameterizedMessageFactory (or ReusableMessageFactory in garbage-free mode) |
| by setting the value of the system property log4j2.messageFactory to the name of the custom |
| MessageFactory class. </p> |
| |
| <p>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. |
| </p> |
| </section> |
| <section> |
| <h3><a name="Lookups"></a>Lookups</h3> |
| |
| <p> |
| 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. |
| </p> |
| |
| <p> |
| A Lookup must be declared using a Plugin annotation with a type of "Lookup". The name specified on |
| the Plugin annotation will be used to match the prefix. Unlike other Plugins, Lookups do not |
| use a PluginFactory. Instead, they are required to provide a constructor that accepts no arguments. |
| The example below shows a Lookup that will return the value of a System Property. |
| </p> |
| |
| <p>The provided Lookups are documented here: <a href="./lookups.html">Lookups</a></p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @Plugin(name = "sys", category = "Lookup") |
| 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); |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="Filters"></a>Filters</h3> |
| |
| <p> |
| As might be expected, Filters are the used to reject or accept log events as they pass through the |
| logging system. A Filter is declared using a Plugin annotation of type "Core" and an elementType of |
| "filter". The name 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 that will be called to |
| create the Filter. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @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 loggerLevel The log Level. |
| * @param match The action to take on a match. |
| * @param mismatch The action to take on a mismatch. |
| * @return The created ThresholdFilter. |
| */ |
| @PluginFactory |
| public static ThresholdFilter createFilter(@PluginAttribute(value = "level", defaultStringValue = "ERROR") Level level, |
| @PluginAttribute(value = "onMatch", defaultStringValue = "NEUTRAL") Result onMatch, |
| @PluginAttribute(value = "onMismatch", defaultStringValue = "DENY") Result onMismatch) { |
| return new ThresholdFilter(level, onMatch, onMismatch); |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="Appenders"></a>Appenders</h3> |
| |
| <p> |
| 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 Plugins with a type of "Core" |
| and an elementType of "appender". The name 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. |
| </p> |
| |
| <p> |
| Appenders must also declare a PluginFactory method that will create the appender. The example |
| below shows an Appender named "Stub" that can be used as an initial template. |
| </p> |
| |
| <p> |
| 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. |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @Plugin(name = "Stub", category = "Core", elementType = "appender", printObject = true) |
| public final class StubAppender extends AbstractOutputStreamAppender<StubManager> { |
| |
| private StubAppender(String name, |
| Layout<? extends Serializable> layout, |
| Filter filter, |
| boolean ignoreExceptions, |
| StubManager manager) { |
| super(name, layout, filter, ignoreExceptions, true, manager); |
| } |
| |
| @PluginFactory |
| public static StubAppender createAppender(@PluginAttribute("name") String name, |
| @PluginAttribute("ignoreExceptions") boolean ignoreExceptions, |
| @PluginElement("Layout") Layout layout, |
| @PluginElement("Filters") Filter filter) { |
| |
| if (name == null) { |
| LOGGER.error("No name provided for StubAppender"); |
| return null; |
| } |
| |
| StubManager manager = StubManager.getStubManager(name); |
| if (manager == null) { |
| return null; |
| } |
| if (layout == null) { |
| layout = PatternLayout.createDefaultLayout(); |
| } |
| return new StubAppender(name, layout, filter, ignoreExceptions, manager); |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="Layouts"></a>Layouts</h3> |
| |
| <p> |
| Layouts perform the formatting of events into the printable text that is written by Appenders to |
| some destination. All Layouts must implement the Layout interface. Layouts that format the |
| event into a String should extend AbstractStringLayout, which will take care of converting the |
| String into the required byte array. |
| </p> |
| |
| <p> |
| Every Layout must declare itself as a plugin using the Plugin annotation. The type must be "Core", |
| and the elementType must be "layout". printObject should be set to true if the plugin's toString |
| method will provide a representation of the object and its parameters. The name of the plugin must |
| match the value users should use to specify it as an element in their Appender configuration. |
| The plugin also must provide a static method annotated as a PluginFactory and with each of the |
| methods parameters annotated with PluginAttr or PluginElement as appropriate. |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @Plugin(name = "SampleLayout", category = "Core", elementType = "layout", printObject = true) |
| public class SampleLayout extends AbstractStringLayout { |
| |
| protected SampleLayout(boolean locationInfo, boolean properties, boolean complete, |
| Charset charset) { |
| } |
| |
| @PluginFactory |
| public static SampleLayout createLayout(@PluginAttribute("locationInfo") boolean locationInfo, |
| @PluginAttribute("properties") boolean properties, |
| @PluginAttribute("complete") boolean complete, |
| @PluginAttribute(value = "charset", defaultStringValue = "UTF-8") Charset charset) { |
| return new SampleLayout(locationInfo, properties, complete, charset); |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="PatternConverters"></a>PatternConverters</h3> |
| |
| <p> |
| PatternConverters are used by the PatternLayout to format the log event into a printable String. Each |
| Converter is responsible for a single kind of manipulation, however Converters are free to format |
| the event in complex ways. For example, there are several converters that manipulate Throwables and |
| format them in various ways. |
| </p> |
| |
| <p> |
| A PatternConverter must first declare itself as a Plugin using the standard Plugin annotation but |
| must specify value of "Converter" on the type attribute. Furthermore, the Converter must also |
| specify the ConverterKeys attribute to define the tokens that can be specified in the pattern |
| (preceded by a '%' character) to identify the Converter. |
| </p> |
| |
| <p> |
| Unlike most other Plugins, Converters do not use a PluginFactory. Instead, each Converter is |
| required to provide a static newInstance method that accepts an array of Strings as the only |
| parameter. The String array are the values that are specified within the curly braces that can |
| follow the converter key. |
| </p> |
| |
| <p> |
| The following shows the skeleton of a Converter plugin. |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @Plugin(name = "query", category = "Converter") |
| @ConverterKeys({"q", "query"}) |
| public final class QueryConverter extends LogEventPatternConverter { |
| |
| public QueryConverter(String[] options) { |
| } |
| |
| public static QueryConverter newInstance(final String[] options) { |
| return new QueryConverter(options); |
| } |
| }</pre></div> |
| </section> |
| <section> |
| <h3><a name="Plugin_Builders"></a>Plugin Builders</h3> |
| |
| <p> |
| 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 <i>Item 2: Consider a builder when |
| faced with many constructor parameters</i> in <i>Effective Java</i> by Joshua Bloch). There are some other |
| advantages to using an annotated builder class over an annotated factory method: |
| </p> |
| |
| <ul> |
| |
| <li>Attribute names don't need to be specified if they match the field name.</li> |
| |
| <li>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).</li> |
| |
| <li>Adding new optional parameters doesn't require existing programmatic configuration to be refactored.</li> |
| |
| <li>Easier to write unit tests using builders rather than factory methods with optional parameters.</li> |
| |
| <li>Default values are specified via code rather than relying on reflection and injection, so they work |
| programmatically as well as in a configuration file.</li> |
| </ul> |
| |
| <p> |
| Here is an example of a plugin factory from ListAppender: |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @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); |
| }</pre></div> |
| |
| <p> |
| Here is that same factory using a builder pattern instead: |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| @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); |
| } |
| }</pre></div> |
| |
| <p> |
| 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. |
| |
| </p> |
| |
| <p> |
| 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). |
| </p> |
| |
| <p> |
| Here is an example of using a plugin factory versus a plugin builder programmatically: |
| </p> |
| |
| <div> |
| <pre class="prettyprint linenums"> |
| ListAppender list1 = ListAppender.createAppender("List1", true, false, null, null); |
| ListAppender list2 = ListAppender.newBuilder().setName("List1").setEntryPerNewLine(true).build(); |
| </pre></div> |
| </section> |
| <section> |
| <h3><a name="Custom_ContextDataInjector"></a>Custom ContextDataInjector</h3> |
| |
| <p> |
| The ContextDataInjector (introduced in Log4j 2.7) is responsible for |
| populating the LogEvent's |
| <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/LogEvent.html#getContextData" class="javadoc">context data</a> |
| with key-value pairs or replacing it completely. |
| The default implementation is ThreadContextDataInjector, which obtains context attributes from the ThreadContext. |
| </p> |
| <p> |
| Applications may replace the default ContextDataInjector by setting the value of the system property |
| log4j2.contextDataInjector to the name of the custom ContextDataInjector class. |
| </p> |
| <p> |
| Implementors should be aware there are some subtleties related to thread-safety and implementing a |
| context data injector in a garbage-free manner. |
| See the <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/ContextDataInjector.html" class="javadoc">ContextDataInjector</a> |
| javadoc for detail. |
| </p> |
| </section> |
| <section> |
| <h3><a name="Custom_ThreadContextMap_implementations"></a>Custom ThreadContextMap implementations</h3> |
| |
| <p> |
| A garbage-free StringMap-based context map can be installed by setting system property log4j2.garbagefreeThreadContextMap |
| to true. (Log4j must be <a href="garbagefree.html#Config">enabled</a> to use ThreadLocals.) |
| </p> |
| <p> |
| Any custom ThreadContextMap implementation can be installed by setting system property |
| log4j2.threadContextMap to the fully qualified class name of the class implementing the |
| ThreadContextMap interface. By also implementing the ReadOnlyThreadContextMap interface, your custom |
| ThreadContextMap implementation will be accessible to applications via the |
| <a href="../log4j-api/apidocs/org/apache/logging/log4j/ThreadContext.html#getThreadContextMap">ThreadContext::getThreadContextMap</a> |
| method. |
| </p> |
| </section> |
| <section> |
| <h3><a name="Custom_Plugins"></a>Custom Plugins</h3> |
| |
| <p>See the <a href="plugins.html">Plugins</a> section of the manual.</p> |
| |
| </section> |
| </section> |
| |
| |
| |
| </main> |
| </div> |
| </div> |
| <hr/> |
| <footer> |
| <div class="container-fluid"> |
| <div class="row-fluid"> |
| <p align="center">Copyright © 1999-2019 <a class="external" href="http://www.apache.org">The Apache Software Foundation</a>. All Rights Reserved.<br> |
| Apache Logging, Apache Log4j, Log4j, Apache, the Apache feather logo, and the Apache Logging project logo are trademarks of The Apache Software Foundation.</p> |
| </div> |
| </div> |
| </footer> |
| </body> |
| </html> |