You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2018/04/08 21:03:48 UTC
[7/7] logging-log4j2 git commit: LOG4J2-1802: Convert programmatic
config manual page to asciidoc
LOG4J2-1802: Convert programmatic config manual page to asciidoc
Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/77a3712d
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/77a3712d
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/77a3712d
Branch: refs/heads/master
Commit: 77a3712df0364e73ae5aa7bbfaaab58c2f738efb
Parents: de9e42e
Author: Matt Sicker <bo...@gmail.com>
Authored: Sun Apr 8 15:22:57 2018 -0500
Committer: Matt Sicker <bo...@gmail.com>
Committed: Sun Apr 8 16:03:36 2018 -0500
----------------------------------------------------------------------
src/site/asciidoc/manual/customconfig.adoc | 386 ++++++++++++++++++++++++
src/site/xdoc/manual/customconfig.xml | 375 -----------------------
2 files changed, 386 insertions(+), 375 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/77a3712d/src/site/asciidoc/manual/customconfig.adoc
----------------------------------------------------------------------
diff --git a/src/site/asciidoc/manual/customconfig.adoc b/src/site/asciidoc/manual/customconfig.adoc
new file mode 100644
index 0000000..7f4c9ea
--- /dev/null
+++ b/src/site/asciidoc/manual/customconfig.adoc
@@ -0,0 +1,386 @@
+////
+ 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.
+////
+= Programmatic Configuration
+Ralph Goers <rg...@apache.org>
+
+Log4j 2 provides a few ways for applications to create their own
+programmatic configuration:
+
+* Specify a custom `ConfigurationFactory` to start Log4j with a
+programmatic configuration
+* Use the `Configurator` to replace the configuration after Log4j started
+* Initialize Log4j with a combination of a configuration file and
+programmatic configuration
+* Modify the current `Configuration` after initialization
+
+[#ConfigurationBuilder]
+== The ConfigurationBuilder API
+
+Starting with release 2.4, Log4j provides a `ConfigurationBuilder` and a
+set of component builders that allow a `Configuration` to be created
+fairly easily. Actual configuration objects like `LoggerConfig` or
+`Appender` can be unwieldy; they require a lot of knowledge about Log4j
+internals which makes them difficult to work with if all you want is to
+create a `Configuration`.
+
+The new `ConfigurationBuilder` API (in the
+`org.apache.logging.log4j.core.config.builder.api` package) allows users
+to create Configurations in code by constructing component
+_definitions_. There is no need to work directly with actual
+configuration objects. Component definitions are added to the
+`ConfigurationBuilder`, and once all the definitions have been collected
+all the actual configuration objects (like Loggers and Appenders) are
+constructed.
+
+`ConfigurationBuilder` has convenience methods for the base components
+that can be configured such as Loggers, Appenders, Filter, Properties,
+etc. However, Log4j 2's plugin mechanism means that users can create any
+number of custom components. As a trade-off, the `ConfigurationBuilder`
+API provides only a limited number of "strongly typed" convenience
+methods like `newLogger()`, `newLayout()` etc. The generic
+`builder.newComponent()` method can be used if no convenience method
+exists for the component you want to configure.
+
+For example, the builder does not know what sub-components can be
+configured on specific components such as the RollingFileAppender vs.
+the RoutingAppender. To specify a triggering policy on a
+RollingFileAppender you would use builder.newComponent().
+
+Examples of using the `ConfigurationBuilder` API are in the sections that
+follow.
+
+[#ConfigurationFactory]
+== Understanding ConfigurationFactory
+
+During initialization, Log4j 2 will search for available
+link:extending.html#ConfigurationFactory[ConfigurationFactories] and
+then select the one to use. The selected `ConfigurationFactory` creates
+the `Configuration` that Log4j will use. Here is how Log4j finds the
+available ConfigurationFactories:
+
+1. A system property named `log4j2.configurationFactory` can be set
+with the name of the ConfigurationFactory to be used.
+2. `ConfigurationFactory.setConfigurationFactory(ConfigurationFactory)`
+can be called with the instance of the `ConfigurationFactory` to be used.
+This must be called before any other calls to Log4j.
+3. A `ConfigurationFactory` implementation can be added to the classpath
+and configured as a plugin in the "ConfigurationFactory" category. The
+`@Order` annotation can be used to specify the relative priority when
+multiple applicable ConfigurationFactories are found.
+
+ConfigurationFactories have the concept of "supported types", which
+basically maps to the file extension of the configuration file that the
+ConfigurationFactory can handle. If a configuration file location is
+specified, ConfigurationFactories whose supported type does not include
+"*" or the matching file extension will not be used.
+
+[#Example]
+== Initialize Log4j Using ConfigurationBuilder with a Custom ConfigurationFactory
+
+One way to programmatically configure Log4j 2 is to create a custom
+`ConfigurationFactory` that uses the
+link:#ConfigurationBuilder[`ConfigurationBuilder`] to create a
+Configuration. The below example overrides the `getConfiguration()`
+method to return a `Configuration` created by the `ConfigurationBuilder`.
+This will cause the `Configuration` to automatically be hooked into Log4j
+when the `LoggerContext` is created. In the example below, because it
+specifies a supported type of "*" it will override any configuration
+files provided.
+
+[source,java]
+----
+@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
+@Order(50)
+public class CustomConfigurationFactory extends ConfigurationFactory {
+
+ static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
+ builder.setConfigurationName(name);
+ builder.setStatusLevel(Level.ERROR);
+ builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL).
+ addAttribute("level", Level.DEBUG));
+ AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
+ addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
+ appenderBuilder.add(builder.newLayout("PatternLayout").
+ addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
+ appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
+ Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
+ builder.add(appenderBuilder);
+ builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
+ add(builder.newAppenderRef("Stdout")).
+ addAttribute("additivity", false));
+ builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
+ return builder.build();
+ }
+
+ @Override
+ public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
+ return getConfiguration(loggerContext, source.toString(), null);
+ }
+
+ @Override
+ public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
+ ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
+ return createConfiguration(name, builder);
+ }
+
+ @Override
+ protected String[] getSupportedTypes() {
+ return new String[] {"*"};
+ }
+}
+----
+
+As of version 2.7, the `ConfigurationFactory.getConfiguration()` methods
+take an additional `LoggerContext` parameter.
+
+[#Configurator]
+== Reconfigure Log4j Using ConfigurationBuilder with the Configurator
+
+An alternative to a custom `ConfigurationFactory` is to configure with the
+`Configurator`. Once a `Configuration` object has been constructed, it can
+be passed to one of the `Configurator.initialize` methods to set up the
+Log4j configuration.
+
+Using the `Configurator` in this manner allows the application control
+over when Log4j is initialized. However, should any logging be attempted
+before `Configurator.initialize()` is called then the default
+configuration will be used for those log events.
+
+[source,java]
+----
+ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
+builder.setStatusLevel(Level.ERROR);
+builder.setConfigurationName("BuilderTest");
+builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
+ .addAttribute("level", Level.DEBUG));
+AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
+ ConsoleAppender.Target.SYSTEM_OUT);
+appenderBuilder.add(builder.newLayout("PatternLayout")
+ .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
+appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY, Filter.Result.NEUTRAL)
+ .addAttribute("marker", "FLOW"));
+builder.add(appenderBuilder);
+builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG)
+ .add(builder.newAppenderRef("Stdout")).addAttribute("additivity", false));
+builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
+ctx = Configurator.initialize(builder.build());
+----
+
+This example shows how to create a configuration that includes a
+RollingFileAppender.
+
+[source,java]
+----
+ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
+
+builder.setStatusLevel(Level.ERROR);
+builder.setConfigurationName("RollingBuilder");
+// create a console appender
+AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
+ ConsoleAppender.Target.SYSTEM_OUT);
+appenderBuilder.add(builder.newLayout("PatternLayout")
+ .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
+builder.add(appenderBuilder);
+// create a rolling file appender
+LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
+ .addAttribute("pattern", "%d [%t] %-5level: %msg%n");
+ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
+ .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
+ .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
+appenderBuilder = builder.newAppender("rolling", "RollingFile")
+ .addAttribute("fileName", "target/rolling.log")
+ .addAttribute("filePattern", "target/archive/rolling-%d{MM-dd-yy}.log.gz")
+ .add(layoutBuilder)
+ .addComponent(triggeringPolicy);
+builder.add(appenderBuilder);
+
+// create the new logger
+builder.add(builder.newLogger("TestLogger", Level.DEBUG)
+ .add(builder.newAppenderRef("rolling"))
+ .addAttribute("additivity", false));
+
+builder.add(builder.newRootLogger(Level.DEBUG)
+ .add(builder.newAppenderRef("rolling")));
+LoggerContext ctx = Configurator.initialize(builder.build());
+----
+
+[#Hybrid]
+== Initialize Log4j by Combining Configuration File with Programmatic Configuration
+
+Sometimes you want to configure with a configuration file but do some
+additional programmatic configuration. A possible use case might be that
+you want to allow for a flexible configuration using XML but at the same
+time make sure there are a few configuration elements that are always
+present that can't be removed.
+
+The easiest way to achieve this is to extend one of the standard
+`Configuration` classes (`XMLConfiguration`, `JSONConfiguration`) and then
+create a new `ConfigurationFactory` for the extended class. After the
+standard configuration completes the custom configuration can be added
+to it.
+
+The example below shows how to extend `XMLConfiguration` to manually add
+an `Appender` and a `LoggerConfig` to the configuration.
+
+[source,java]
+----
+@Plugin(name = "MyXMLConfigurationFactory", category = "ConfigurationFactory")
+@Order(10)
+public class MyXMLConfigurationFactory extends ConfigurationFactory {
+
+ /**
+ * Valid file extensions for XML files.
+ */
+ public static final String[] SUFFIXES = new String[] {".xml", "*"};
+
+ /**
+ * Return the Configuration.
+ * @param source The InputSource.
+ * @return The Configuration.
+ */
+ public Configuration getConfiguration(InputSource source) {
+ return new MyXMLConfiguration(source, configFile);
+ }
+
+ /**
+ * Returns the file suffixes for XML files.
+ * @return An array of File extensions.
+ */
+ public String[] getSupportedTypes() {
+ return SUFFIXES;
+ }
+}
+
+public class MyXMLConfiguration extends XMLConfiguration {
+ public MyXMLConfiguration(final ConfigurationFactory.ConfigurationSource configSource) {
+ super(configSource);
+ }
+
+ @Override
+ protected void doConfigure() {
+ super.doConfigure();
+ final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+ final Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
+ null,null, null);
+ final Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
+ "false", "false", "4000", layout, null, "false", null, config);
+ appender.start();
+ addAppender(appender);
+ LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
+ "true", refs, null, config, null );
+ loggerConfig.addAppender(appender, null, null);
+ addLogger("org.apache.logging.log4j", loggerConfig);
+ }
+}
+----
+
+[#AddingToCurrent]
+== Programmatically Modifying the Current Configuration after Initialization
+
+Applications sometimes have the need to customize logging separate from
+the actual configuration. Log4j allows this although it suffers from a
+few limitations:
+
+1. If the configuration file is changed the configuration will be
+reloaded and the manual changes will be lost.
+2. Modification to the running configuration requires that all the
+methods being called (addAppender and addLogger) be synchronized.
+
+As such, the recommended approach for customizing a configuration is to
+extend one of the standard Configuration classes, override the setup
+method to first do super.setup() and then add the custom Appenders,
+Filters and LoggerConfigs to the configuration before it is registered
+for use.
+
+The following example adds an Appender and a new LoggerConfig using that
+Appender to the current configuration.
+
+//TODO: update code example below with new plugin API
+[source,java]
+----
+ final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
+ final Configuration config = ctx.getConfiguration();
+ Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
+ null,null, null);
+ Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
+ "false", "false", "4000", layout, null, "false", null, config);
+ appender.start();
+ config.addAppender(appender);
+ AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
+ AppenderRef[] refs = new AppenderRef[] {ref};
+ LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
+ "true", refs, null, config, null );
+ loggerConfig.addAppender(appender, null, null);
+ config.addLogger("org.apache.logging.log4j", loggerConfig);
+ ctx.updateLoggers();
+}
+----
+
+[#AppendingToWritersAndOutputStreams]
+== Appending Log Events to Writers and OutputStreams Programmatically
+
+Log4j 2.5 provides facilities to append log events to Writers and
+OutputStreams. For example, this provides simple integration for JDBC
+Driver implementors that use Log4j internally and still want to support
+the JDBC APIs `CommonDataSource.setLogWriter(PrintWriter)`,
+`java.sql.DriverManager.setLogWriter(PrintWriter)`, and
+`java.sql.DriverManager.setLogStream(PrintStream)`.
+
+Given any `Writer`, like a `PrintWriter`, you tell Log4j to append
+events to that writer by creating a `WriterAppender` and updating the
+Log4j configuration:
+
+[source,java]
+----
+void addAppender(final Writer writer, final String writerName) {
+ final LoggerContext context = LoggerContext.getContext(false);
+ final Configuration config = context.getConfiguration();
+ final PatternLayout layout = PatternLayout.createDefaultLayout(config);
+ final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true);
+ appender.start();
+ config.addAppender(appender);
+ updateLoggers(appender, config);
+}
+
+private void updateLoggers(final Appender appender, final Configuration config) {
+ final Level level = null;
+ final Filter filter = null;
+ for (final LoggerConfig loggerConfig : config.getLoggers().values()) {
+ loggerConfig.addAppender(appender, level, filter);
+ }
+ config.getRootLogger().addAppender(appender, level, filter);
+}
+----
+
+You can achieve the same effect with an `OutputStream`, like a
+`PrintStream`:
+
+[source,java]
+----
+void addAppender(final OutputStream outputStream, final String outputStreamName) {
+ final LoggerContext context = LoggerContext.getContext(false);
+ final Configuration config = context.getConfiguration();
+ final PatternLayout layout = PatternLayout.createDefaultLayout(config);
+ final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
+ appender.start();
+ config.addAppender(appender);
+ updateLoggers(appender, config);
+}
+----
+
+The difference is the use of `OutputStreamAppender` instead of
+`WriterAppender`.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/77a3712d/src/site/xdoc/manual/customconfig.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/customconfig.xml b/src/site/xdoc/manual/customconfig.xml
deleted file mode 100644
index e57af39..0000000
--- a/src/site/xdoc/manual/customconfig.xml
+++ /dev/null
@@ -1,375 +0,0 @@
-<?xml version="1.0"?>
-<!--
- 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
-
- http://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.
--->
-
-<document xmlns="http://maven.apache.org/XDOC/2.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
- <properties>
- <title>Extending Log4j 2 Configuration</title>
- <author email="rgoers@apache.org">Ralph Goers</author>
- </properties>
-
- <body>
- <section name="Programmatic Configuration">
- <p>
- Log4j 2 provides a few ways for applications to create their own programmatic configuration:
- </p>
- <ul>
- <li>Specify a custom ConfigurationFactory to start Log4j with a programmatic configuration</li>
- <li>Use the Configurator to replace the configuration after Log4j started</li>
- <li>Initialize Log4j with a combination of a configuration file and programmatic configuration</li>
- <li>Modify the current Configuration after initialization</li>
- </ul>
- <a name="ConfigurationBuilder"/>
- <subsection name="The ConfigurationBuilder API">
- <p>
- Starting with release 2.4, Log4j provides a ConfigurationBuilder and a set of component builders that
- allow a Configuration to be created fairly easily.
- Actual configuration objects like LoggerConfig or Appender can be unwieldy; they require a lot
- of knowledge about Log4j internals which makes them difficult to work with if all you want is to
- create a Configuration.
- </p>
- <p>
- The new ConfigurationBuilder API (in the <code>org.apache.logging.log4j.core.config.builder.api</code> package)
- allows users to create Configurations in code by constructing component <i>definitions</i>.
- There is no need to work directly with actual configuration objects.
- Component definitions are added to the ConfigurationBuilder, and once all the definitions have
- been collected all the actual configuration objects (like Loggers and Appenders) are constructed.
- </p>
- <p>
- ConfigurationBuilder has convenience methods for the base components that can be configured such as
- Loggers, Appenders, Filter, Properties, etc.
- However, Log4j 2's plugin mechanism means that users can create any number of custom components.
- As a trade-off, the ConfigurationBuilder API provides only a limited number of "strongly typed"
- convenience methods like <code>newLogger()</code>, <code>newLayout()</code> etc.
- The generic <code>builder.newComponent()</code> method can be used if no convenience method exists
- for the component you want to configure.
- </p>
- <p>
- For example, the builder does not know what sub-components can be configured on specific components
- such as the RollingFileAppender vs. the RoutingAppender. To specify a triggering policy on a
- RollingFileAppender you would use builder.newComponent().
- </p>
- <p>
- Examples of using the ConfigurationBuilder API are in the sections that follow.
- </p>
- </subsection>
- <a name="ConfigurationFactory"/>
- <subsection name="Understanding ConfigurationFactory">
- <p>
- During initialization, Log4j 2 will search for available <a href="extending.html#ConfigurationFactory">ConfigurationFactories</a>
- and then select the one to use. The
- selected ConfigurationFactory creates the Configuration that Log4j will use. Here is how Log4j finds
- the available ConfigurationFactories:
- </p>
- <ol>
- <li>A system property named <tt>log4j2.configurationFactory</tt> can be set with the name of the ConfigurationFactory to be used.</li>
- <li><code>ConfigurationFactory.setConfigurationFactory(ConfigurationFactory)</code> can be called with the instance of the
- ConfigurationFactory to be used. This must be called before any other calls to Log4j.</li>
- <li>A ConfigurationFactory implementation can be added to the classpath and configured as a plugin
- in the "ConfigurationFactory" category.
- The Order annotation can be used to specify the relative priority when multiple applicable
- ConfigurationFactories are found.</li>
- </ol>
- <p>
- ConfigurationFactories have the concept of "supported types", which basically maps to the
- file extension of the configuration file that the ConfigurationFactory can handle.
- If a configuration file location is specified, ConfigurationFactories whose supported type
- does not include "*" or the matching file extension will not be used.
- </p>
- </subsection>
- <a name="Example"/>
- <subsection name="Initialize Log4j Using ConfigurationBuilder with a Custom ConfigurationFactory">
- <p>
- One way to programmatically configure Log4j 2 is to create a custom ConfigurationFactory
- that uses the <a href="#ConfigurationBuilder">ConfigurationBuilder</a> to create a Configuration.
- The below example overrides the <code>getConfiguration()</code> method to return a
- Configuration created by the ConfigurationBuilder.
- This will cause the Configuration to automatically be hooked into Log4j when the LoggerContext is created.
- In the example below, because it specifies a supported type of "*" it will override any configuration files provided.
- </p>
- <pre class="prettyprint linenum"><![CDATA[
-@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
-@Order(50)
-public class CustomConfigurationFactory extends ConfigurationFactory {
-
- static Configuration createConfiguration(final String name, ConfigurationBuilder<BuiltConfiguration> builder) {
- builder.setConfigurationName(name);
- builder.setStatusLevel(Level.ERROR);
- builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL).
- addAttribute("level", Level.DEBUG));
- AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").
- addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
- appenderBuilder.add(builder.newLayout("PatternLayout").
- addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
- appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY,
- Filter.Result.NEUTRAL).addAttribute("marker", "FLOW"));
- builder.add(appenderBuilder);
- builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG).
- add(builder.newAppenderRef("Stdout")).
- addAttribute("additivity", false));
- builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
- return builder.build();
- }
-
- @Override
- public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
- return getConfiguration(loggerContext, source.toString(), null);
- }
-
- @Override
- public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
- ConfigurationBuilder<BuiltConfiguration> builder = newConfigurationBuilder();
- return createConfiguration(name, builder);
- }
-
- @Override
- protected String[] getSupportedTypes() {
- return new String[] {"*"};
- }
-}]]></pre>
- <p>
- As of version 2.7, the <code>ConfigurationFactory.getConfiguration()</code> methods take an
- additional <code>LoggerContext</code> parameter.
- </p>
- </subsection>
- <a name="Configurator"/>
- <subsection name="Reconfigure Log4j Using ConfigurationBuilder with the Configurator">
- <p>
- An alternative to a custom ConfigurationFactory is to configure with the <code>Configurator</code>.
- Once a Configuration object has been constructed, it can be passed to one of the
- <code>Configurator.initialize</code> methods to set up the Log4j configuration.
- </p>
- <p>
- Using the Configurator in this manner allows the application control over when Log4j is initialized.
- However, should any logging be attempted before Configurator.initialize() is called then the
- default configuration will be used for those log events.
- </p>
- <pre class="prettyprint linenum"><![CDATA[
-ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
-builder.setStatusLevel(Level.ERROR);
-builder.setConfigurationName("BuilderTest");
-builder.add(builder.newFilter("ThresholdFilter", Filter.Result.ACCEPT, Filter.Result.NEUTRAL)
- .addAttribute("level", Level.DEBUG));
-AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
- ConsoleAppender.Target.SYSTEM_OUT);
-appenderBuilder.add(builder.newLayout("PatternLayout")
- .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
-appenderBuilder.add(builder.newFilter("MarkerFilter", Filter.Result.DENY, Filter.Result.NEUTRAL)
- .addAttribute("marker", "FLOW"));
-builder.add(appenderBuilder);
-builder.add(builder.newLogger("org.apache.logging.log4j", Level.DEBUG)
- .add(builder.newAppenderRef("Stdout")).addAttribute("additivity", false));
-builder.add(builder.newRootLogger(Level.ERROR).add(builder.newAppenderRef("Stdout")));
-ctx = Configurator.initialize(builder.build());
-]]></pre>
- <p>This example shows how to create a configuration that includes a RollingFileAppender.</p>
- <pre class="prettyprint linenum"><![CDATA[
-ConfigurationBuilder< BuiltConfiguration > builder = ConfigurationBuilderFactory.newConfigurationBuilder();
-
-builder.setStatusLevel( Level.ERROR);
-builder.setConfigurationName("RollingBuilder");
-// create a console appender
-AppenderComponentBuilder appenderBuilder = builder.newAppender("Stdout", "CONSOLE").addAttribute("target",
- ConsoleAppender.Target.SYSTEM_OUT);
-appenderBuilder.add(builder.newLayout("PatternLayout")
- .addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable"));
-builder.add( appenderBuilder );
-// create a rolling file appender
-LayoutComponentBuilder layoutBuilder = builder.newLayout("PatternLayout")
- .addAttribute("pattern", "%d [%t] %-5level: %msg%n");
-ComponentBuilder triggeringPolicy = builder.newComponent("Policies")
- .addComponent(builder.newComponent("CronTriggeringPolicy").addAttribute("schedule", "0 0 0 * * ?"))
- .addComponent(builder.newComponent("SizeBasedTriggeringPolicy").addAttribute("size", "100M"));
-appenderBuilder = builder.newAppender("rolling", "RollingFile")
- .addAttribute("fileName", "target/rolling.log")
- .addAttribute("filePattern", "target/archive/rolling-%d{MM-dd-yy}.log.gz")
- .add(layoutBuilder)
- .addComponent(triggeringPolicy);
-builder.add(appenderBuilder);
-
-// create the new logger
-builder.add( builder.newLogger( "TestLogger", Level.DEBUG )
- .add( builder.newAppenderRef( "rolling" ) )
- .addAttribute( "additivity", false ) );
-
-builder.add( builder.newRootLogger( Level.DEBUG )
- .add( builder.newAppenderRef( "rolling" ) ) );
-LoggerContext ctx = Configurator.initialize(builder.build());
-]]></pre>
- </subsection>
-
- <a name="Hybrid"/>
- <subsection name="Initialize Log4j by Combining Configuration File with Programmatic Configuration">
- <p>
- Sometimes you want to configure with a configuration file but do some additional programmatic
- configuration. A possible use case might be that you want to allow for a flexible configuration using XML
- but at the same time make sure there are a few configuration elements that are always present that can't be removed.
- </p>
- <p>
- The easiest way to achieve this is to extend one of the standard Configuration classes
- (XMLConfiguration, JSONConfiguration) and then create a new ConfigurationFactory for the extended class.
- After the standard configuration completes the custom configuration can be added to it.
- </p>
- <p>
- The example below shows how to extend XMLConfiguration to manually add an Appender and a LoggerConfig
- to the configuration.
- </p>
- <pre class="prettyprint linenums">
-@Plugin(name = "MyXMLConfigurationFactory", category = "ConfigurationFactory")
-@Order(10)
-public class MyXMLConfigurationFactory extends ConfigurationFactory {
-
- /**
- * Valid file extensions for XML files.
- */
- public static final String[] SUFFIXES = new String[] {".xml", "*"};
-
- /**
- * Return the Configuration.
- * @param source The InputSource.
- * @return The Configuration.
- */
- public Configuration getConfiguration(InputSource source) {
- return new MyXMLConfiguration(source, configFile);
- }
-
- /**
- * Returns the file suffixes for XML files.
- * @return An array of File extensions.
- */
- public String[] getSupportedTypes() {
- return SUFFIXES;
- }
-}
-
-public class MyXMLConfiguration extends XMLConfiguration {
- public MyXMLConfiguration(final ConfigurationFactory.ConfigurationSource configSource) {
- super(configSource);
- }
-
- @Override
- protected void doConfigure() {
- super.doConfigure();
- final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
- final Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
- null,null, null);
- final Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
- "false", "false", "4000", layout, null, "false", null, config);
- appender.start();
- addAppender(appender);
- LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
- "true", refs, null, config, null );
- loggerConfig.addAppender(appender, null, null);
- addLogger("org.apache.logging.log4j", loggerConfig);
- }
-}</pre>
- </subsection>
- <a name="AddingToCurrent"/>
- <subsection name="Programmatically Modifying the Current Configuration after Initialization">
- <p>
- Applications sometimes have the need to customize logging separate from the actual configuration.
- Log4j allows this although it suffers from a few limitations:
- </p>
- <ol>
- <li>If the configuration file is changed the configuration will be reloaded and the manual changes
- will be lost.</li>
- <li>Modification to the running configuration requires that all the methods being called (addAppender
- and addLogger) be synchronized.</li>
- </ol>
- <p>
- As such, the recommended approach for customizing a configuration is to extend one of the standard
- Configuration classes, override the setup method to first do super.setup() and then add the custom
- Appenders, Filters and LoggerConfigs to the configuration before it is registered for use.
- </p>
- <p>
- The following example adds an Appender and a new LoggerConfig using that Appender to the current
- configuration.
- </p>
- <!-- TODO: update code example below with new plugin API -->
- <pre class="prettyprint linenums"><![CDATA[
- final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
- final Configuration config = ctx.getConfiguration();
- Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
- null,null, null);
- Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
- "false", "false", "4000", layout, null, "false", null, config);
- appender.start();
- config.addAppender(appender);
- AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
- AppenderRef[] refs = new AppenderRef[] {ref};
- LoggerConfig loggerConfig = LoggerConfig.createLogger("false", "info", "org.apache.logging.log4j",
- "true", refs, null, config, null );
- loggerConfig.addAppender(appender, null, null);
- config.addLogger("org.apache.logging.log4j", loggerConfig);
- ctx.updateLoggers();
-}]]></pre>
- </subsection>
- <a name="AppendingToWritersAndOutputStreams"/>
- <subsection name="Appending Log Events to Writers and OutputStreams Programmatically">
- <p>
- Log4j 2.5 provides facilities to append log events to Writers and OutputStreams. For example, this
- provides simple integration for JDBC Driver implementors that use Log4j internally and still want
- to support the JDBC APIs <code>CommonDataSource.setLogWriter(PrintWriter)</code>,
- <code>java.sql.DriverManager.setLogWriter(PrintWriter)</code>, and
- <code>java.sql.DriverManager.setLogStream(PrintStream)</code>.
- </p>
- <p>
- Given any <code>Writer</code>, like a <code>PrintWriter</code>, you tell Log4j to append events to
- that writer by creating a <code>WriterAppender</code> and updating the Log4j configuration:
- </p>
- <pre class="prettyprint linenums"><![CDATA[
-void addAppender(final Writer writer, final String writerName) {
- final LoggerContext context = LoggerContext.getContext(false);
- final Configuration config = context.getConfiguration();
- final PatternLayout layout = PatternLayout.createDefaultLayout(config);
- final Appender appender = WriterAppender.createAppender(layout, null, writer, writerName, false, true);
- appender.start();
- config.addAppender(appender);
- updateLoggers(appender, config);
-}
-
-private void updateLoggers(final Appender appender, final Configuration config) {
- final Level level = null;
- final Filter filter = null;
- for (final LoggerConfig loggerConfig : config.getLoggers().values()) {
- loggerConfig.addAppender(appender, level, filter);
- }
- config.getRootLogger().addAppender(appender, level, filter);
-}]]></pre>
- <p>
- You can achieve the same effect with an <code>OutputStream</code>, like a <code>PrintStream</code>:
- </p>
- <pre class="prettyprint linenums"><![CDATA[
-void addAppender(final OutputStream outputStream, final String outputStreamName) {
- final LoggerContext context = LoggerContext.getContext(false);
- final Configuration config = context.getConfiguration();
- final PatternLayout layout = PatternLayout.createDefaultLayout(config);
- final Appender appender = OutputStreamAppender.createAppender(layout, null, outputStream, outputStreamName, false, true);
- appender.start();
- config.addAppender(appender);
- updateLoggers(appender, config);
-}]]></pre>
- </subsection>
- <p>
- The difference is the use of <code>OutputStreamAppender</code> instead of <code>WriterAppender</code>.
- </p>
- </section>
-
- </body>
-</document>