You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2016/04/26 07:48:11 UTC

[01/38] logging-log4j2 git commit: LOG4J2-494 working CompositeConfiguration

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 2d16d346d -> 988ed5093


LOG4J2-494 working CompositeConfiguration


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/bb64f457
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/bb64f457
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/bb64f457

Branch: refs/heads/master
Commit: bb64f457730864b70e3b932c2156c5522245d909
Parents: 4195c7b
Author: Ralph Goers <rg...@nextiva.com>
Authored: Sat Apr 23 23:29:57 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Sat Apr 23 23:29:57 2016 -0700

----------------------------------------------------------------------
 .../apache/logging/log4j/util/LoaderUtil.java   |   8 +-
 log4j-core/${filename}                          |   0
 .../core/config/AbstractConfiguration.java      |  26 +-
 .../log4j/core/config/ConfigurationFactory.java |  66 +++--
 .../log4j/core/config/ConfigurationSource.java  |  51 +++-
 .../core/config/ConfiguratonFileWatcher.java    |   4 +
 .../logging/log4j/core/config/Configurator.java |  46 +++-
 .../composite/CompositeConfiguration.java       | 168 +++++++++++++
 .../config/composite/DefaultMergeStrategy.java  | 252 +++++++++++++++++++
 .../core/config/composite/MergeStrategy.java    |  33 +++
 .../core/config/composite/package-info.java     |  21 ++
 .../log4j/core/impl/Log4jContextFactory.java    |  43 +++-
 .../logging/log4j/core/util/WatchManager.java   |   9 +
 .../core/config/CompositeConfigurationTest.java | 149 +++++++++++
 .../src/test/resources/log4j-comp-appender.json |  34 +++
 .../src/test/resources/log4j-comp-appender.xml  |  39 +++
 .../src/test/resources/log4j-comp-filter.json   |   9 +
 .../src/test/resources/log4j-comp-filter.xml    |  34 +++
 .../src/test/resources/log4j-comp-logger.json   |  36 +++
 .../src/test/resources/log4j-comp-logger.xml    |  41 +++
 .../test/resources/log4j-comp-properties.json   |  16 ++
 .../test/resources/log4j-comp-properties.xml    |  34 +++
 22 files changed, 1072 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
index 096d945..c2d55a2 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LoaderUtil.java
@@ -28,7 +28,7 @@ import java.util.Objects;
 
 /**
  * <em>Consider this class private.</em> Utility class for ClassLoaders.
- * 
+ *
  * @see ClassLoader
  * @see RuntimePermission
  * @see Thread#getContextClassLoader()
@@ -135,14 +135,14 @@ public final class LoaderUtil {
      * @throws InvocationTargetException if there was an exception whilst constructing the class
      * @since 2.1
      */
-    public static Object newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
+    public static <T> T newInstanceOf(final String className) throws ClassNotFoundException, IllegalAccessException,
             InstantiationException, NoSuchMethodException, InvocationTargetException {
         final Class<?> clazz = loadClass(className);
         try {
-            return clazz.getConstructor().newInstance();
+            return (T) clazz.getConstructor().newInstance();
         } catch (final NoSuchMethodException ignored) {
             // FIXME: looking at the code for Class.newInstance(), this seems to do the same thing as above
-            return clazz.newInstance();
+            return (T) clazz.newInstance();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/${filename}
----------------------------------------------------------------------
diff --git a/log4j-core/${filename} b/log4j-core/${filename}
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
index 00cd397..316381a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/AbstractConfiguration.java
@@ -98,6 +98,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
     protected boolean isShutdownHookEnabled = true;
 
     /**
+     * The Script manager.
+     */
+    protected ScriptManager scriptManager;
+
+    /**
      * The Advertiser which exposes appender configurations to external systems.
      */
     private Advertiser advertiser = new DefaultAdvertiser();
@@ -113,7 +118,6 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
     private LoggerConfig root = new LoggerConfig();
     private final ConcurrentMap<String, Object> componentMap = new ConcurrentHashMap<>();
     private final ConfigurationSource configurationSource;
-    private ScriptManager scriptManager;
     private final ConfigurationScheduler configurationScheduler = new ConfigurationScheduler();
     private final WatchManager watchManager = new WatchManager(configurationScheduler);
     private AsyncLoggerConfigDisruptor asyncLoggerConfigDisruptor;
@@ -151,6 +155,18 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         return scriptManager;
     }
 
+    public void setScriptManager(ScriptManager scriptManager) {
+        this.scriptManager = scriptManager;
+    }
+
+    public PluginManager getPluginManager() {
+        return pluginManager;
+    }
+
+    public void setPluginManager(PluginManager pluginManager) {
+        this.pluginManager = pluginManager;
+    }
+
     @Override
     public WatchManager getWatchManager() {
         return watchManager;
@@ -161,7 +177,11 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         return configurationScheduler;
     }
 
-	@Override
+    public Node getRootNode() {
+        return rootNode;
+    }
+
+    @Override
 	public AsyncLoggerConfigDelegate getAsyncLoggerConfigDelegate() {
 	    // lazily instantiate only when requested by AsyncLoggers:
 	    // loading AsyncLoggerConfigDisruptor requires LMAX Disruptor jar on classpath
@@ -357,7 +377,7 @@ public abstract class AbstractConfiguration extends AbstractFilterable implement
         return isShutdownHookEnabled;
     }
 
-    protected void setup() {
+    public void setup() {
     }
 
     protected Level getDefaultStatus() {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
index 8f3d764..41f3571 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
@@ -36,6 +36,7 @@ import java.util.concurrent.locks.ReentrantLock;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.config.builder.api.ConfigurationBuilderFactory;
+import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
 import org.apache.logging.log4j.core.lookup.Interpolator;
@@ -392,32 +393,21 @@ public abstract class ConfigurationFactory extends ConfigurationBuilderFactory {
                 final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties()
                         .getStringProperty(CONFIGURATION_FILE_PROPERTY));
                 if (configLocationStr != null) {
-                    ConfigurationSource source = null;
-                    try {
-                        source = getInputFromUri(NetUtils.toURI(configLocationStr));
-                    } catch (final Exception ex) {
-                        // Ignore the error and try as a String.
-                        LOGGER.catching(Level.DEBUG, ex);
-                    }
-                    if (source == null) {
-                        final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
-                        source = getInputFromString(configLocationStr, loader);
-                    }
-                    if (source != null) {
-                        for (final ConfigurationFactory factory : getFactories()) {
-                            final String[] types = factory.getSupportedTypes();
-                            if (types != null) {
-                                for (final String type : types) {
-                                    if (type.equals("*") || configLocationStr.endsWith(type)) {
-                                        final Configuration config = factory.getConfiguration(source);
-                                        if (config != null) {
-                                            return config;
-                                        }
-                                    }
-                                }
+                    String[] sources = configLocationStr.split(",");
+                    if (sources.length > 1) {
+                        List<AbstractConfiguration> configs = new ArrayList<>();
+                        for (String sourceLocation : sources) {
+                            Configuration config = getConfiguration(sourceLocation);
+                            if (config != null && config instanceof AbstractConfiguration) {
+                                configs.add((AbstractConfiguration) config);
+                            } else {
+                                LOGGER.error("Failed to created configuration at {}", sourceLocation);
+                                return null;
                             }
                         }
+                        return new CompositeConfiguration(configs);
                     }
+                    return getConfiguration(configLocationStr);
                 } else {
                     for (final ConfigurationFactory factory : getFactories()) {
                         final String[] types = factory.getSupportedTypes();
@@ -468,6 +458,36 @@ public abstract class ConfigurationFactory extends ConfigurationBuilderFactory {
             return new DefaultConfiguration();
         }
 
+        private Configuration getConfiguration(String configLocationStr) {
+            ConfigurationSource source = null;
+            try {
+                source = getInputFromUri(NetUtils.toURI(configLocationStr));
+            } catch (final Exception ex) {
+                // Ignore the error and try as a String.
+                LOGGER.catching(Level.DEBUG, ex);
+            }
+            if (source == null) {
+                final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
+                source = getInputFromString(configLocationStr, loader);
+            }
+            if (source != null) {
+                for (final ConfigurationFactory factory : getFactories()) {
+                    final String[] types = factory.getSupportedTypes();
+                    if (types != null) {
+                        for (final String type : types) {
+                            if (type.equals("*") || configLocationStr.endsWith(type)) {
+                                final Configuration config = factory.getConfiguration(source);
+                                if (config != null) {
+                                    return config;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            return null;
+        }
+
         private Configuration getConfiguration(final boolean isTest, final String name) {
             final boolean named = Strings.isNotEmpty(name);
             final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
index edb2d75..f1627bb 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationSource.java
@@ -23,6 +23,8 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Objects;
 
@@ -44,7 +46,7 @@ public class ConfigurationSource {
     /**
      * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified
      * file.
-     * 
+     *
      * @param stream the input stream
      * @param file the file where the input stream originated
      */
@@ -59,7 +61,7 @@ public class ConfigurationSource {
     /**
      * Constructs a new {@code ConfigurationSource} with the specified input stream that originated from the specified
      * url.
-     * 
+     *
      * @param stream the input stream
      * @param url the URL where the input stream originated
      */
@@ -74,7 +76,7 @@ public class ConfigurationSource {
     /**
      * Constructs a new {@code ConfigurationSource} with the specified input stream. Since the stream is the only source
      * of data, this constructor makes a copy of the stream contents.
-     * 
+     *
      * @param stream the input stream
      * @throws IOException if an exception occurred reading from the specified stream
      */
@@ -92,7 +94,7 @@ public class ConfigurationSource {
 
     /**
      * Returns the contents of the specified {@code InputStream} as a byte array.
-     * 
+     *
      * @param inputStream the stream to read
      * @return the contents of the specified stream
      * @throws IOException if a problem occurred reading from the stream
@@ -113,7 +115,7 @@ public class ConfigurationSource {
     /**
      * Returns the file configuration source, or {@code null} if this configuration source is based on an URL or has
      * neither a file nor an URL.
-     * 
+     *
      * @return the configuration source file, or {@code null}
      */
     public File getFile() {
@@ -123,7 +125,7 @@ public class ConfigurationSource {
     /**
      * Returns the configuration source URL, or {@code null} if this configuration source is based on a file or has
      * neither a file nor an URL.
-     * 
+     *
      * @return the configuration source URL, or {@code null}
      */
     public URL getURL() {
@@ -131,9 +133,40 @@ public class ConfigurationSource {
     }
 
     /**
+     * Returns a URI representing the configuration resource or null if it cannot be determined.
+     * @return The URI.
+     */
+    public URI getURI() {
+        URI sourceURI = null;
+        if (url != null) {
+            try {
+                sourceURI = url.toURI();
+            } catch (URISyntaxException ex) {
+                    /* Ignore the exception */
+            }
+        }
+        if (sourceURI == null && file != null) {
+            sourceURI = file.toURI();
+        }
+        if (sourceURI == null && location != null) {
+            try {
+                sourceURI = new URI(location);
+            } catch (URISyntaxException ex) {
+                // Assume the scheme was missing.
+                try {
+                    sourceURI = new URI("file://" + location);
+                } catch (URISyntaxException uriEx) {
+                    /* Ignore the exception */
+                }
+            }
+        }
+        return sourceURI;
+    }
+
+    /**
      * Returns a string describing the configuration source file or URL, or {@code null} if this configuration source
      * has neither a file nor an URL.
-     * 
+     *
      * @return a string describing the configuration source file or URL, or {@code null}
      */
     public String getLocation() {
@@ -142,7 +175,7 @@ public class ConfigurationSource {
 
     /**
      * Returns the input stream that this configuration source was constructed with.
-     * 
+     *
      * @return the input stream that this configuration source was constructed with.
      */
     public InputStream getInputStream() {
@@ -151,7 +184,7 @@ public class ConfigurationSource {
 
     /**
      * Returns a new {@code ConfigurationSource} whose input stream is reset to the beginning.
-     * 
+     *
      * @return a new {@code ConfigurationSource}
      * @throws IOException if a problem occurred while opening the new input stream
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
index e268c54..82d06ab 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfiguratonFileWatcher.java
@@ -35,6 +35,10 @@ public class ConfiguratonFileWatcher implements FileWatcher {
         this.listeners = listeners;
     }
 
+    public List<ConfigurationListener> getListeners() {
+        return listeners;
+    }
+
 
     @Override
     public void fileModified(File file) {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
index fe6a5d5..f0e462e 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
@@ -17,6 +17,8 @@
 package org.apache.logging.log4j.core.config;
 
 import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.logging.log4j.Level;
@@ -109,8 +111,24 @@ public final class Configurator {
      */
     public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation,
             final Object externalContext) {
-        final URI uri = Strings.isBlank(configLocation) ? null : NetUtils.toURI(configLocation);
-        return initialize(name, loader, uri, externalContext);
+        if (Strings.isBlank(configLocation)) {
+            return initialize(name, loader, (URI) null, externalContext);
+        }
+        if (configLocation.contains(",")) {
+            String[] parts = configLocation.split(",");
+            String scheme = null;
+            List<URI> uris = new ArrayList<>(parts.length);
+            for (String part : parts) {
+                URI uri = NetUtils.toURI(scheme != null ? scheme + ":" + part : part);
+                if (scheme == null && uri.getScheme() != null) {
+                    scheme = uri.getScheme();
+                }
+                uris.add(uri);
+            }
+            return initialize(name, loader, uris, externalContext);
+        } else {
+            return initialize(name, loader, NetUtils.toURI(configLocation), externalContext);
+        }
     }
 
     /**
@@ -146,6 +164,20 @@ public final class Configurator {
         return null;
     }
 
+    public static LoggerContext initialize(final String name, final ClassLoader loader, final List<URI> configLocations,
+            final Object externalContext) {
+        try {
+            final Log4jContextFactory factory = getFactory();
+            return factory == null ?
+                    null :
+                    factory.getContext(FQCN, loader, externalContext, false, configLocations, name);
+        } catch (final Exception ex) {
+            LOGGER.error("There was a problem initializing the LoggerContext [{}] using configurations at [{}].", name,
+                    configLocations, ex);
+        }
+        return null;
+    }
+
     /**
      * Initializes the Logging Context.
      * @param name The Context name.
@@ -202,7 +234,7 @@ public final class Configurator {
     public static void setAllLevels(final String parentLogger, final Level level) {
         // 1) get logger config
         // 2) if exact match, use it, if not, create it.
-        // 3) set level on logger config 
+        // 3) set level on logger config
         // 4) update child logger configs with level
         // 5) update loggers
         final LoggerContext loggerContext = LoggerContext.getContext(false);
@@ -225,10 +257,10 @@ public final class Configurator {
         }
         return set;
     }
-    
+
     /**
      * Sets logger levels.
-     * 
+     *
      * @param levelMap
      *            a levelMap where keys are level names and values are new
      *            Levels.
@@ -249,7 +281,7 @@ public final class Configurator {
 
     /**
      * Sets a logger's level.
-     * 
+     *
      * @param loggerName
      *            the logger name
      * @param level
@@ -283,7 +315,7 @@ public final class Configurator {
 
     /**
      * Sets the root logger's level.
-     * 
+     *
      * @param level
      *            the new level
      */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
new file mode 100644
index 0000000..8b416b3
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.core.config.composite;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.ConfigurationSource;
+import org.apache.logging.log4j.core.config.ConfiguratonFileWatcher;
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.Reconfigurable;
+import org.apache.logging.log4j.core.config.plugins.util.ResolverUtil;
+import org.apache.logging.log4j.core.config.status.StatusConfiguration;
+import org.apache.logging.log4j.core.util.FileWatcher;
+import org.apache.logging.log4j.core.util.Patterns;
+import org.apache.logging.log4j.core.util.WatchManager;
+import org.apache.logging.log4j.util.LoaderUtil;
+import org.apache.logging.log4j.util.PropertiesUtil;
+
+/**
+ * A Composite Configuration.
+ */
+public class CompositeConfiguration extends AbstractConfiguration implements Reconfigurable {
+
+    /**
+     * Allow the ConfigurationFactory class to be specified as a system property.
+     */
+    public static final String MERGE_STRATEGY_PROPERTY = "log4j.mergeStrategy";
+
+    private static final String[] VERBOSE_CLASSES = new String[] {ResolverUtil.class.getName()};
+
+    private List<? extends AbstractConfiguration> configurations;
+
+    private MergeStrategy mergeStrategy;
+
+    /**
+     * Construct the ComponsiteConfiguration.
+     *
+     * @param configurations The List of Configurations to merge.
+     */
+    public CompositeConfiguration(List<? extends AbstractConfiguration> configurations) {
+        super(ConfigurationSource.NULL_SOURCE);
+        this.configurations = configurations;
+        String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY,
+                DefaultMergeStrategy.class.getName());
+        try {
+            mergeStrategy = LoaderUtil.newInstanceOf(mergeStrategyClassName);
+        } catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | InvocationTargetException |
+                InstantiationException ex) {
+            mergeStrategy = new DefaultMergeStrategy();
+        }
+    }
+
+    @Override
+    public void setup() {
+        AbstractConfiguration targetConfiguration = configurations.get(0);
+        staffChildConfiguration(targetConfiguration);
+        WatchManager watchManager = targetConfiguration.getWatchManager();
+        rootNode = targetConfiguration.getRootNode();
+        for (AbstractConfiguration sourceConfiguration : configurations.subList(1, configurations.size())) {
+            staffChildConfiguration(sourceConfiguration);
+            Node sourceRoot = sourceConfiguration.getRootNode();
+            mergeStrategy.mergConfigurations(rootNode, sourceRoot, getPluginManager());
+            if (LOGGER.isEnabled(Level.ALL)) {
+                StringBuilder sb = new StringBuilder();
+                printNodes("", rootNode, sb);
+                System.out.println(sb.toString());
+            }
+            int monitorInterval = sourceConfiguration.getWatchManager().getIntervalSeconds();
+            if (monitorInterval > 0) {
+                if (monitorInterval < watchManager.getIntervalSeconds()) {
+                    watchManager.setIntervalSeconds(monitorInterval);
+                }
+                WatchManager sourceWatchManager = sourceConfiguration.getWatchManager();
+                Map<File, FileWatcher> watchers = sourceWatchManager.getWatchers();
+                FileWatcher fileWatcher = new ConfiguratonFileWatcher(this, listeners);
+                for (Map.Entry<File, FileWatcher> entry : watchers.entrySet()) {
+                    if (entry.getValue() instanceof ConfiguratonFileWatcher) {
+                        watchManager.watchFile(entry.getKey(), fileWatcher);
+                    }
+                }
+            }
+        }
+        final StatusConfiguration statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES)
+                .withStatus(getDefaultStatus());
+        for (final Map.Entry<String, String> entry : rootNode.getAttributes().entrySet()) {
+            final String key = entry.getKey();
+            final String value = getStrSubstitutor().replace(entry.getValue());
+            if ("status".equalsIgnoreCase(key)) {
+                statusConfig.withStatus(value);
+            } else if ("dest".equalsIgnoreCase(key)) {
+                statusConfig.withDestination(value);
+            } else if ("shutdownHook".equalsIgnoreCase(key)) {
+                isShutdownHookEnabled = !"disable".equalsIgnoreCase(value);
+            } else if ("verbose".equalsIgnoreCase(key)) {
+                statusConfig.withVerbosity(value);
+            } else if ("packages".equalsIgnoreCase(key)) {
+                pluginPackages.addAll(Arrays.asList(value.split(Patterns.COMMA_SEPARATOR)));
+            } else if ("name".equalsIgnoreCase(key)) {
+                setName(value);
+            }
+        }
+        statusConfig.initialize();
+    }
+
+    @Override
+    public Configuration reconfigure() {
+        List<AbstractConfiguration> configs = new ArrayList<>();
+        ConfigurationFactory factory = ConfigurationFactory.getInstance();
+        for (AbstractConfiguration config : configurations) {
+            ConfigurationSource source = config.getConfigurationSource();
+            URI sourceURI = source.getURI();
+            Configuration currentConfig;
+            if (sourceURI != null) {
+                LOGGER.warn("Unable to determine URI for configuration {}, changes to it will be ignored",
+                        config.getName());
+                currentConfig = factory.getConfiguration(config.getName(), sourceURI);
+                if (currentConfig == null) {
+                    LOGGER.warn("Unable to reload configuration {}, changes to it will be ignored", config.getName());
+                    currentConfig = config;
+                }
+            } else {
+                currentConfig = config;
+            }
+            configs.add((AbstractConfiguration) currentConfig);
+
+        }
+
+        return new CompositeConfiguration(configs);
+    }
+
+    private void staffChildConfiguration(AbstractConfiguration childConfiguration) {
+        childConfiguration.setPluginManager(pluginManager);
+        childConfiguration.setScriptManager(scriptManager);
+        childConfiguration.setup();
+    }
+
+    private void printNodes(String indent, Node node, StringBuilder sb) {
+        sb.append(indent).append(node.getName()).append(" type: ").append(node.getType()).append("\n");
+        sb.append(indent).append(node.getAttributes().toString()).append("\n");
+        for (Node child : node.getChildren()) {
+            printNodes(indent + "  ", child, sb);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
new file mode 100644
index 0000000..7b123a0
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.core.config.composite;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
+import org.apache.logging.log4j.core.config.plugins.util.PluginType;
+import org.apache.logging.log4j.core.filter.CompositeFilter;
+
+/**
+ * The default merge strategy for composite configurations.
+ * <p>
+ * The default merge strategy performs the merge according to the following rules:
+ * <ol>
+ * <li>Aggregates the global configuration attributes with those in later configurations replacing those in previous
+ * configurations with the exception that the highest status level and the lowest monitorInterval greater than 0 will
+ * be used.</li>
+ * <li>Properties from all configurations are aggregated. Duplicate properties replace those in previous
+ * configurations.</li>
+ * <li>Filters are aggregated under a CompositeFilter if more than one Filter is defined. Since Filters are not named
+ * duplicates may be present.</li>
+ * <li>Scripts and ScriptFile references are aggregated. Duplicate definiations replace those in previous
+ * configurations.</li>
+ * <li>Appenders are aggregated. Appenders with the same name are replaced by those in later configurations, including
+ * all of the Appender's subcomponents.</li>
+ * <li>Loggers are all aggregated. Logger attributes are individually merged with duplicates being replaced by those
+ * in later configurations. Appender references on a Logger are aggregated with duplicates being replaced by those in
+ * later configurations. Filters on a Logger are aggregated under a CompositeFilter if more than one Filter is defined.
+ * Since Filters are not named duplicates may be present. Filters under Appender references included or discarded
+ * depending on whether their parent Appender reference is kept or discarded.</li>
+ * </ol>
+ */
+public class DefaultMergeStrategy implements MergeStrategy {
+
+    private static final String APPENDERS = "appenders";
+    private static final String PROPERTIES = "properties";
+    private static final String LOGGERS = "loggers";
+    private static final String SCRIPTS = "scripts";
+    private static final String FILTERS = "filters";
+    private static final String STATUS = "status";
+    private static final String NAME = "name";
+    private static final String REF = "ref";
+
+    /**
+     * Merge the source Configuration into the target Configuration.
+     *
+     * @param target        The target node to merge into.
+     * @param source        The source node.
+     * @param pluginManager The PluginManager.
+     */
+    public void mergConfigurations(Node target, Node source, PluginManager pluginManager) {
+        for (Map.Entry<String, String> attribute : source.getAttributes().entrySet()) {
+            boolean isFound = false;
+            for (Map.Entry<String, String> targetAttribute : target.getAttributes().entrySet()) {
+                if (targetAttribute.getKey().equalsIgnoreCase(attribute.getKey())) {
+                    if (attribute.getKey().equalsIgnoreCase(STATUS)) {
+                        Level targetLevel = Level.getLevel(targetAttribute.getValue());
+                        Level sourceLevel = Level.getLevel(attribute.getValue());
+                        if (targetLevel != null && sourceLevel != null) {
+                            if (sourceLevel.isLessSpecificThan(targetLevel)) {
+                                targetAttribute.setValue(attribute.getValue());
+                            }
+                        }
+                    } else {
+                        if (attribute.getKey().equalsIgnoreCase("monitorInterval")) {
+                            int sourceInterval = Integer.parseInt(attribute.getValue());
+                            int targetInterval = Integer.parseInt(targetAttribute.getValue());
+                            if (targetInterval == 0 || sourceInterval < targetInterval) {
+                                targetAttribute.setValue(attribute.getValue());
+                            }
+                        } else {
+                            targetAttribute.setValue(attribute.getValue());
+                        }
+                    }
+                    isFound = true;
+                }
+            }
+            if (!isFound) {
+                target.getAttributes().put(attribute.getKey(), attribute.getValue());
+            }
+        }
+        for (Node sourceChildNode : source.getChildren()) {
+            boolean isFilter = isFilterNode(sourceChildNode);
+            boolean isMerged = false;
+            for (Node targetChildNode : target.getChildren()) {
+                if (isFilter) {
+                    if (isFilterNode(targetChildNode)) {
+                        updateFilterNode(target, targetChildNode, sourceChildNode, pluginManager);
+                        isMerged = true;
+                        break;
+                    } else {
+                        continue;
+                    }
+                }
+
+                if (!targetChildNode.getName().equalsIgnoreCase(sourceChildNode.getName())) {
+                    continue;
+                }
+
+                switch (targetChildNode.getName().toLowerCase()) {
+                    case PROPERTIES:
+                    case SCRIPTS:
+                    case APPENDERS: {
+                        for (Node node : sourceChildNode.getChildren()) {
+                            for (Node targetNode : targetChildNode.getChildren()) {
+                                if (targetNode.getAttributes().get(NAME).equals(node.getAttributes().get(NAME))) {
+                                    targetChildNode.getChildren().remove(targetNode);
+                                    break;
+                                }
+                            }
+                            targetChildNode.getChildren().add(node);
+                        }
+                        isMerged = true;
+                        break;
+                    }
+                    case LOGGERS: {
+                        Map<String, Node> targetLoggers = new HashMap<>();
+                        for (Node node : targetChildNode.getChildren()) {
+                            targetLoggers.put(node.getName(), node);
+                        }
+                        for (Node node : sourceChildNode.getChildren()) {
+                            Node targetNode = getLoggerNode(targetChildNode, node.getAttributes().get(NAME));
+                            Node loggerNode = new Node(targetChildNode, node.getName(), node.getType());
+                            if (targetNode != null) {
+                                for (Node sourceLoggerChild : node.getChildren()) {
+                                    if (isFilterNode(sourceLoggerChild)) {
+                                        boolean foundFilter = false;
+                                        for (Node targetChild : targetNode.getChildren()) {
+                                            if (isFilterNode(targetChild)) {
+                                                updateFilterNode(loggerNode, targetChild, sourceLoggerChild,
+                                                        pluginManager);
+                                                foundFilter = true;
+                                                break;
+                                            }
+                                        }
+                                        if (!foundFilter) {
+                                            Node childNode = new Node(loggerNode, sourceLoggerChild.getName(),
+                                                    sourceLoggerChild.getType());
+                                            targetNode.getChildren().add(childNode);
+                                        }
+                                    } else {
+                                        Node childNode = new Node(loggerNode, sourceLoggerChild.getName(),
+                                                sourceLoggerChild.getType());
+                                        childNode.getAttributes().putAll(sourceLoggerChild.getAttributes());
+                                        if (childNode.getName().equalsIgnoreCase("AppenderRef")) {
+                                            for (Node targetChild : targetNode.getChildren()) {
+                                                if (isSameReference(targetChild, childNode)) {
+                                                    targetNode.getChildren().remove(targetChild);
+                                                    break;
+                                                }
+                                            }
+                                        } else {
+                                            for (Node targetChild : targetNode.getChildren()) {
+                                                if (isSameName(targetChild, childNode)) {
+                                                    targetNode.getChildren().remove(targetChild);
+                                                    break;
+                                                }
+                                            }
+                                        }
+
+                                        targetNode.getChildren().add(childNode);
+                                    }
+                                }
+                            } else {
+                                loggerNode.getAttributes().putAll(node.getAttributes());
+                                loggerNode.getChildren().addAll(node.getChildren());
+                                targetChildNode.getChildren().add(loggerNode);
+                            }
+                        }
+                        isMerged = true;
+                        break;
+                    }
+                    default: {
+                        targetChildNode.getChildren().addAll(sourceChildNode.getChildren());
+                        isMerged = true;
+                        break;
+                    }
+
+                }
+            }
+            if (!isMerged) {
+                target.getChildren().add(sourceChildNode);
+            }
+        }
+    }
+
+    private Node getLoggerNode(Node parentNode, String name) {
+        for (Node node : parentNode.getChildren()) {
+            String nodeName = node.getAttributes().get(NAME);
+            if (name == null && nodeName == null) {
+                return node;
+            }
+            if (nodeName != null && nodeName.equals(name)) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    private void updateFilterNode(Node target, Node targetChildNode, Node sourceChildNode,
+            PluginManager pluginManager) {
+        if (CompositeFilter.class.isAssignableFrom(targetChildNode.getType().getPluginClass())) {
+            Node node = new Node(targetChildNode, sourceChildNode.getName(), sourceChildNode.getType());
+            node.getChildren().addAll(sourceChildNode.getChildren());
+            node.getAttributes().putAll(sourceChildNode.getAttributes());
+            targetChildNode.getChildren().add(node);
+        } else {
+            PluginType pluginType = pluginManager.getPluginType(FILTERS);
+            Node filtersNode = new Node(targetChildNode, FILTERS, pluginType);
+            Node node = new Node(filtersNode, sourceChildNode.getName(), sourceChildNode.getType());
+            node.getAttributes().putAll(sourceChildNode.getAttributes());
+            List<Node> children = filtersNode.getChildren();
+            children.add(targetChildNode);
+            children.add(node);
+            List<Node> nodes = target.getChildren();
+            nodes.remove(targetChildNode);
+            nodes.add(filtersNode);
+        }
+    }
+
+    private boolean isFilterNode(Node node) {
+        return Filter.class.isAssignableFrom(node.getType().getPluginClass());
+    }
+
+    private boolean isSameName(Node node1, Node node2) {
+        return node1.getAttributes().get(NAME).toLowerCase().equals(node2.getAttributes().get(NAME).toLowerCase());
+    }
+
+    private boolean isSameReference(Node node1, Node node2) {
+        return node1.getAttributes().get(REF).toLowerCase().equals(node2.getAttributes().get(REF).toLowerCase());
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
new file mode 100644
index 0000000..130a6f0
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.core.config.composite;
+
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
+
+/**
+ * Merges two configurations together
+ */
+public interface MergeStrategy {
+
+    /**
+     * Merge the soure node tree into the target node tree.
+     * @param target The target Node tree.
+     * @param source The source Node tree.
+     */
+    void mergConfigurations(Node target, Node source, PluginManager pluginManager);
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java
new file mode 100644
index 0000000..fd920fa
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Support for composite configurations.
+ */
+package org.apache.logging.log4j.core.config.composite;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
index c65a64f..b504838 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jContextFactory.java
@@ -17,10 +17,14 @@
 package org.apache.logging.log4j.core.impl;
 
 import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 import org.apache.logging.log4j.core.LifeCycle;
 import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
+import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
 import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.config.ConfigurationSource;
@@ -241,6 +245,43 @@ public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallba
         return ctx;
     }
 
+    public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
+            final boolean currentContext, final List<URI> configLocations, final String name) {
+        final LoggerContext ctx = selector
+                .getContext(fqcn, loader, currentContext, null/*this probably needs to change*/);
+        if (externalContext != null && ctx.getExternalContext() == null) {
+            ctx.setExternalContext(externalContext);
+        }
+        if (name != null) {
+            ctx.setName(name);
+        }
+        if (ctx.getState() == LifeCycle.State.INITIALIZED) {
+            if ((configLocations != null && !configLocations.isEmpty())) {
+                ContextAnchor.THREAD_CONTEXT.set(ctx);
+                List<AbstractConfiguration> configurations = new ArrayList<>(configLocations.size());
+                for (URI configLocation : configLocations) {
+                    Configuration currentReadConfiguration = ConfigurationFactory.getInstance()
+                            .getConfiguration(name, configLocation);
+                    if (currentReadConfiguration instanceof AbstractConfiguration) {
+                        configurations.add((AbstractConfiguration) currentReadConfiguration);
+                    } else {
+                        LOGGER.error(
+                                "Found configuration {}, which is not an AbstractConfiguration and can't be handled by CompositeConfiguration",
+                                configLocation);
+                    }
+                }
+                CompositeConfiguration compositeConfiguration = new CompositeConfiguration(configurations);
+                LOGGER.debug("Starting LoggerContext[name={}] from configurations at {}", ctx.getName(),
+                        configLocations);
+                ctx.start(compositeConfiguration);
+                ContextAnchor.THREAD_CONTEXT.remove();
+            } else {
+                ctx.start();
+            }
+        }
+        return ctx;
+    }
+
     /**
      * Returns the ContextSelector.
      * @return The ContextSelector.
@@ -251,7 +292,7 @@ public class Log4jContextFactory implements LoggerContextFactory, ShutdownCallba
 
 	/**
 	 * Returns the ShutdownCallbackRegistry
-	 * 
+	 *
 	 * @return the ShutdownCallbackRegistry
 	 * @since 2.4
 	 */

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
index 3750462..146bff7 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core.util;
 
 import java.io.File;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -78,6 +79,14 @@ public class WatchManager extends AbstractLifeCycle {
 
     }
 
+    public Map<File, FileWatcher> getWatchers() {
+        Map<File, FileWatcher> map = new HashMap<>();
+        for (Map.Entry<File, FileMonitor> entry : watchers.entrySet()) {
+            map.put(entry.getKey(), entry.getValue().fileWatcher);
+        }
+        return map;
+    }
+
     private class WatchWorker implements Runnable {
 
         @Override

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
new file mode 100644
index 0000000..f17c941
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
@@ -0,0 +1,149 @@
+package org.apache.logging.log4j.core.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.apache.logging.log4j.core.appender.FileAppender;
+import org.apache.logging.log4j.core.appender.RollingFileAppender;
+import org.apache.logging.log4j.core.config.composite.CompositeConfiguration;
+import org.apache.logging.log4j.core.filter.CompositeFilter;
+import org.apache.logging.log4j.core.filter.ThresholdFilter;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+public class CompositeConfigurationTest
+{
+
+    @Test
+    public void compositeConfigurationUsed()
+    {
+        final LoggerContextRule lcr =
+            new LoggerContextRule( "classpath:log4j-comp-appender.xml,log4j-comp-appender.json" );
+        Statement test = new Statement()
+        {
+            @Override
+            public void evaluate()
+                throws Throwable
+            {
+                assertTrue( lcr.getConfiguration() instanceof CompositeConfiguration);
+            }
+        };
+        runTest( lcr, test );
+    }
+
+    @Test
+    public void compositeProperties()
+    {
+        final LoggerContextRule lcr =
+            new LoggerContextRule( "classpath:log4j-comp-properties.xml,log4j-comp-properties.json" );
+        Statement test = new Statement()
+        {
+            @Override
+            public void evaluate()
+                throws Throwable
+            {
+                CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
+                assertEquals( "json", config.getStrSubstitutor().replace( "${propertyShared}" ) );
+                assertEquals( "xml", config.getStrSubstitutor().replace( "${propertyXml}" ) );
+                assertEquals( "json", config.getStrSubstitutor().replace( "${propertyJson}" ) );
+            }
+        };
+        runTest( lcr, test );
+    }
+
+    @Test
+    public void compositeAppenders()
+    {
+        final LoggerContextRule lcr =
+            new LoggerContextRule( "classpath:log4j-comp-appender.xml,log4j-comp-appender.json" );
+        Statement test = new Statement()
+        {
+            @Override
+            public void evaluate()
+                throws Throwable
+            {
+                CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
+                Map<String, Appender> appender = config.getAppenders();
+                assertEquals( 3, appender.size() );
+                assertTrue( appender.get( "STDOUT" ) instanceof ConsoleAppender );
+                assertTrue( appender.get( "File" ) instanceof FileAppender );
+                assertTrue( appender.get( "Override" ) instanceof RollingFileAppender );
+            }
+        };
+        runTest( lcr, test );
+    }
+
+    @Test
+    public void compositeLogger()
+    {
+        final LoggerContextRule lcr = new LoggerContextRule( "classpath:log4j-comp-logger.xml,log4j-comp-logger.json" );
+        Statement test = new Statement()
+        {
+            @Override
+            public void evaluate()
+                throws Throwable
+            {
+                CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
+                Map<String, Appender> appendersMap = config.getLogger( "cat1" ).getAppenders();
+                assertEquals("Expected 2 Appender references for cat1 but got " + appendersMap.size(), 2,
+                        appendersMap.size() );
+                assertTrue( appendersMap.get( "STDOUT" ) instanceof ConsoleAppender );
+
+                appendersMap = config.getLogger( "cat2" ).getAppenders();
+                assertEquals("Expected 1 Appender reference for cat2 but got " + appendersMap.size(), 1,
+                        appendersMap.size() );
+                assertTrue( appendersMap.get( "File" ) instanceof FileAppender );
+
+                appendersMap = config.getLogger( "cat3" ).getAppenders();
+                assertEquals("Expected 1 Appender reference for cat3 but got " + appendersMap.size(), 1,
+                        appendersMap.size() );
+                assertTrue( appendersMap.get( "File" ) instanceof FileAppender );
+
+                appendersMap = config.getRootLogger().getAppenders();
+                assertEquals("Expected 2 Appender references for the root logger but got " + appendersMap.size(), 2,
+                        appendersMap.size() );
+                assertTrue( appendersMap.get( "File" ) instanceof FileAppender );
+                assertTrue( appendersMap.get( "STDOUT" ) instanceof ConsoleAppender );
+            }
+        };
+        runTest( lcr, test );
+    }
+
+    @Test
+    public void overrideFilter()
+    {
+        final LoggerContextRule lcr = new LoggerContextRule( "classpath:log4j-comp-filter.xml,log4j-comp-filter.json" );
+        Statement test = new Statement()
+        {
+            @Override
+            public void evaluate()
+                throws Throwable
+            {
+                CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
+                assertTrue( config.getFilter() instanceof CompositeFilter);
+                CompositeFilter filter = (CompositeFilter) config.getFilter();
+                assertTrue( filter.getFiltersArray().length == 2);
+            }
+        };
+        runTest( lcr, test );
+    }
+
+    private void runTest( LoggerContextRule rule, Statement statement )
+    {
+        try
+        {
+            rule.apply( statement, Description.createTestDescription( getClass(),
+                Thread.currentThread().getStackTrace()[1].getMethodName() ) ).evaluate();
+        }
+        catch ( Throwable throwable )
+        {
+            throw new RuntimeException( throwable );
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-appender.json
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-appender.json b/log4j-core/src/test/resources/log4j-comp-appender.json
new file mode 100644
index 0000000..1f0b02d
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-appender.json
@@ -0,0 +1,34 @@
+{
+    "Configuration" : {
+        "status": "warn",
+        "name": "YAMLConfigTest",
+        "appenders": {
+            "Console": {
+                "name": "STDOUT",
+                "PatternLayout": {
+                    "Pattern": "%m%n"
+                }
+            },
+            "RollingFile": {
+                "name": "Override",
+                "fileName": "target/log4j-appender-override.log",
+                "filePattern": "target/log4j-appender-override-$${date:yyyy-MM}.log",
+                "PatternLayout": {
+                    "Pattern": "%m%n"
+                },
+                "SizeBasedTriggeringPolicy": {
+                    "size": "500"
+                }
+            }
+        },
+        "Loggers" : {
+            "Root" : {
+                "level" : "error",
+                "AppenderRef" : {
+                    "ref" : "STDOUT"
+                }
+
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-appender.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-appender.xml b/log4j-core/src/test/resources/log4j-comp-appender.xml
new file mode 100644
index 0000000..7cd71a2
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-appender.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration status="ERROR" name="XMLConfigTest">
+    <Appenders>
+        <File name="File" fileName="target/log4j-comp-appender.log" bufferedIO="false">
+            <PatternLayout>
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+            </PatternLayout>
+        </File>
+        <File name="Override" fileName="target/log4j-comp-appender.log" bufferedIO="false">
+            <PatternLayout>
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+            </PatternLayout>
+        </File>
+    </Appenders>
+
+    <Loggers>
+        <Root level="ERROR">
+            <AppenderRef ref="File"/>
+        </Root>
+    </Loggers>
+
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-filter.json
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-filter.json b/log4j-core/src/test/resources/log4j-comp-filter.json
new file mode 100644
index 0000000..c010298
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-filter.json
@@ -0,0 +1,9 @@
+{
+    "Configuration" : {
+        "status": "warn",
+        "name": "YAMLConfigTest",
+        "thresholdFilter" : {
+            "level": "debug"
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-filter.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-filter.xml b/log4j-core/src/test/resources/log4j-comp-filter.xml
new file mode 100644
index 0000000..553d448
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-filter.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration status="ERROR" name="XMLConfigTest">
+  <BurstFilter level="INFO" rate="16" maxBurst="100"/>
+
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+  </Appenders>
+
+  <Loggers>
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-logger.json
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-logger.json b/log4j-core/src/test/resources/log4j-comp-logger.json
new file mode 100644
index 0000000..b2b08d7
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-logger.json
@@ -0,0 +1,36 @@
+{
+    "Configuration" : {
+        "status": "warn",
+        "name": "LoggerConfigTest",
+        "Loggers" : {
+            "logger" : [
+                {
+                    "name" : "cat1",
+                    "level" : "debug",
+                    "additivity" : false,
+                    "AppenderRef" : {
+                        "ref" : "STDOUT"
+                    }
+                },
+                {
+                    "name" : "cat2",
+                    "level" : "debug",
+                    "additivity" : false,
+                    "AppenderRef" : {
+                        "ref" : "File"
+                    }
+
+                }
+            ],
+            "Root" : {
+                "level" : "error",
+                "AppenderRef" : [{
+                    "ref" : "STDOUT"
+                },
+                {
+                    "ref" : "File"
+                }]
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-logger.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-logger.xml b/log4j-core/src/test/resources/log4j-comp-logger.xml
new file mode 100644
index 0000000..0934e94
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-logger.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration status="ERROR" name="LoggerConfigTest">
+    <Appenders>
+        <Console name="STDOUT">
+            <PatternLayout pattern="%m%n"/>
+        </Console>
+        <File name="File" fileName="${filename}" bufferedIO="false">
+            <PatternLayout>
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+            </PatternLayout>
+        </File>
+    </Appenders>
+
+    <Loggers>
+        <Logger name="cat1" level="debug" additivity="false">
+            <AppenderRef ref="File"/>
+        </Logger>
+
+        <Logger name="cat3" level="debug" additivity="false">
+            <AppenderRef ref="File"/>
+        </Logger>
+    </Loggers>
+
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-properties.json
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-properties.json b/log4j-core/src/test/resources/log4j-comp-properties.json
new file mode 100644
index 0000000..83c2d09
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-properties.json
@@ -0,0 +1,16 @@
+{
+    "Configuration" : {
+        "status": "warn",
+        "name": "YAMLConfigTest",
+
+        "properties" : {
+            "property" : [{
+                "name" : "propertyShared",
+                "value": "json"
+            },{
+                "name" : "propertyJson",
+                "value": "json"
+            }]
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb64f457/log4j-core/src/test/resources/log4j-comp-properties.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-properties.xml b/log4j-core/src/test/resources/log4j-comp-properties.xml
new file mode 100644
index 0000000..6fa9c6b
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-properties.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration status="OFF" name="XMLConfigTest">
+  <Properties>
+    <Property name="propertyShared">xml</Property>
+    <Property name="propertyXml">xml</Property>
+  </Properties>
+  <Appenders>
+    <Console name="STDOUT">
+      <PatternLayout pattern="%m%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Root level="error">
+      <AppenderRef ref="STDOUT"/>
+    </Root>
+  </Loggers>
+</Configuration>


[27/38] logging-log4j2 git commit: LOG4J2-1297 small syntax edits

Posted by rg...@apache.org.
LOG4J2-1297 small syntax edits


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/26d87c37
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/26d87c37
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/26d87c37

Branch: refs/heads/master
Commit: 26d87c37236ff200d57e18d5bebb41491fa945c8
Parents: 7730ae5
Author: rpopma <rp...@apache.org>
Authored: Mon Apr 25 23:49:21 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 src/site/xdoc/manual/garbagefree.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/26d87c37/src/site/xdoc/manual/garbagefree.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/garbagefree.xml b/src/site/xdoc/manual/garbagefree.xml
index c9e8692..6222a45 100644
--- a/src/site/xdoc/manual/garbagefree.xml
+++ b/src/site/xdoc/manual/garbagefree.xml
@@ -359,8 +359,8 @@ public void garbageFree() {
 
         <a name="Throughput" />
         <h4>Throughput of Garbage-free Logging May Be Worse (But It's All Relative)</h4>
-        <p>Log4j 2.6 in garbage-free mode has the highest throughput in single-threaded scenarios. In multi-threaded
-          scenarios,  Log4j 2.6 "classic" has highest throughput, with Log4j 2.6 in garbage-free mode and Log4j 2.5
+        <p>In our measurements, Log4j 2.6 in garbage-free mode had the highest throughput in single-threaded scenarios. In multi-threaded
+          scenarios,  Log4j 2.6 "classic" had the highest throughput, with Log4j 2.6 in garbage-free mode and Log4j 2.5
           not far behind. Our test results suggest that the throughput of all other logging frameworks rapidly
           declines in multi-threaded applications.</p>
         <p>The graph below compares Log4j 2.6 in garbage-free mode to Log4j 2.6 "classic" mode (which allocates
@@ -369,7 +369,7 @@ public void garbageFree() {
           Log4j 1.2.17, Logback and JUL use their respective File appenders. ImmediateFlush was set to <tt>false</tt> for all
           loggers that support this. The JUL results are for the <tt>XMLFormatter</tt> (which in our measurements was
           about twice as fast as the <tt>SimpleFormatter</tt>).</p>
-        <p>The synchronous logging throughput results below are generated with the
+        <p>The synchronous logging throughput results below are obtained with the
           <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
           See the <tt>org.apache.logging.log4j.perf.jmh.FileAppenderBenchmark</tt> source code in the log4j-perf module.</p>
         <p><img src="../images/garbage-free2.6-SyncThroughputLinux.png"


[36/38] logging-log4j2 git commit: LOG4J2-1297 minor edits

Posted by rg...@apache.org.
LOG4J2-1297 minor edits


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/fdaefaa5
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/fdaefaa5
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/fdaefaa5

Branch: refs/heads/master
Commit: fdaefaa50b81ab3fb0fff487c381f1afab799fda
Parents: 26d87c3
Author: rpopma <rp...@apache.org>
Authored: Mon Apr 25 23:51:45 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:31 2016 -0700

----------------------------------------------------------------------
 src/site/xdoc/manual/garbagefree.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fdaefaa5/src/site/xdoc/manual/garbagefree.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/garbagefree.xml b/src/site/xdoc/manual/garbagefree.xml
index 6222a45..c6cf8ca 100644
--- a/src/site/xdoc/manual/garbagefree.xml
+++ b/src/site/xdoc/manual/garbagefree.xml
@@ -361,8 +361,8 @@ public void garbageFree() {
         <h4>Throughput of Garbage-free Logging May Be Worse (But It's All Relative)</h4>
         <p>In our measurements, Log4j 2.6 in garbage-free mode had the highest throughput in single-threaded scenarios. In multi-threaded
           scenarios,  Log4j 2.6 "classic" had the highest throughput, with Log4j 2.6 in garbage-free mode and Log4j 2.5
-          not far behind. Our test results suggest that the throughput of all other logging frameworks rapidly
-          declines in multi-threaded applications.</p>
+          not far behind. Our test results suggest that the throughput of the other logging frameworks we tested
+          will rapidly decline in multi-threaded applications.</p>
         <p>The graph below compares Log4j 2.6 in garbage-free mode to Log4j 2.6 "classic" mode (which allocates
           temporary objects for every logging call), Log4j 2.5, Log4j 1.2.17, Logback 1.1.7 and
           Java util logging (JUL) on Oracle Java 1.8.0_45. All Log4j 2.x results use the RandomAccessFile appender.


[31/38] logging-log4j2 git commit: LOG4J2-1373 update Logger wrapper Generate tool for new methods added to the Logger interface

Posted by rg...@apache.org.
LOG4J2-1373 update Logger wrapper Generate tool for new methods added to the Logger interface


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/31c76c7f
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/31c76c7f
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/31c76c7f

Branch: refs/heads/master
Commit: 31c76c7f3dcc3fd9eafc7709763ed7094e1d6372
Parents: bb53479
Author: rpopma <rp...@apache.org>
Authored: Sat Apr 23 11:41:55 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/tools/Generate.java      | 467 ++++++++++++++++++-
 1 file changed, 449 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/31c76c7f/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
index ac62c51..c86004d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
@@ -72,6 +72,7 @@ public final class Generate {
                         + "/**%n" //
                         + " * Custom Logger interface with convenience methods for%n" //
                         + " * %s%n" //
+                        + " * <p>Compatible with Log4j 2.6 or higher.</p>%n" //
                         + " */%n" //
                         + "public final class %s implements Serializable {%n" //
                         + "    private static final long serialVersionUID = " + System.nanoTime() + "L;%n" //
@@ -117,6 +118,7 @@ public final class Generate {
                         + "/**%n" //
                         + " * Extended Logger interface with convenience methods for%n" //
                         + " * %s%n" //
+                        + " * <p>Compatible with Log4j 2.6 or higher.</p>%n" //
                         + " */%n" //
                         + "public final class %s extends ExtendedLoggerWrapper {%n" //
                         + "    private static final long serialVersionUID = " + System.nanoTime() + "L;%n" //
@@ -190,8 +192,9 @@ public final class Generate {
             + "     *            a warning if mismatched.%n" //
             + "     * @return The custom Logger.%n" //
             + "     */%n" //
-            + "    public static CLASSNAME create(final Class<?> loggerName, final MessageFactory factory) {%n" //
-            + "        final Logger wrapped = LogManager.getLogger(loggerName, factory);%n" //
+            + "    public static CLASSNAME create(final Class<?> loggerName, final MessageFactory" //
+            + " messageFactory) {%n" //
+            + "        final Logger wrapped = LogManager.getLogger(loggerName, messageFactory);%n" //
             + "        return new CLASSNAME(wrapped);%n" //
             + "    }%n" //
             + "%n" //
@@ -221,8 +224,8 @@ public final class Generate {
             + "     *            a warning if mismatched.%n" //
             + "     * @return The custom Logger.%n" //
             + "     */%n" //
-            + "    public static CLASSNAME create(final Object value, final MessageFactory factory) {%n" //
-            + "        final Logger wrapped = LogManager.getLogger(value, factory);%n" //
+            + "    public static CLASSNAME create(final Object value, final MessageFactory messageFactory) {%n" //
+            + "        final Logger wrapped = LogManager.getLogger(value, messageFactory);%n" //
             + "        return new CLASSNAME(wrapped);%n" //
             + "    }%n" //
             + "%n" //
@@ -248,8 +251,8 @@ public final class Generate {
             + "     *            a warning if mismatched.%n" //
             + "     * @return The custom Logger.%n" //
             + "     */%n" //
-            + "    public static CLASSNAME create(final String name, final MessageFactory factory) {%n" //
-            + "        final Logger wrapped = LogManager.getLogger(name, factory);%n" //
+            + "    public static CLASSNAME create(final String name, final MessageFactory messageFactory) {%n" //
+            + "        final Logger wrapped = LogManager.getLogger(name, messageFactory);%n" //
             + "        return new CLASSNAME(wrapped);%n" //
             + "    }%n";
 
@@ -287,6 +290,17 @@ public final class Generate {
             + "    }%n" //
             + "%n" //
             + "    /**%n" //
+            + "     * Logs a message CharSequence with the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message CharSequence to log.%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final CharSequence message) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, (Throwable) null);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
             + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" //
             + "     * the {@link Throwable} {@code t} passed as parameter.%n" //
             + "     * %n" //
@@ -299,6 +313,19 @@ public final class Generate {
             + "    }%n" //
             + "%n" //
             + "    /**%n" //
+            + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" //
+            + "     * the {@link Throwable} {@code t} passed as parameter.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the CharSequence to log.%n" //
+            + "     * @param t the exception to log, including its stack trace.%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final CharSequence message, final Throwable t) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, t);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
             + "     * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" //
             + "     * %n" //
             + "     * @param marker the marker data specific to this log statement%n" //
@@ -321,6 +348,202 @@ public final class Generate {
             + "    }%n" //
             + "%n" //
             + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @param p7 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" //
+            + "            final Object p7) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6, p7);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @param p7 parameter to the message.%n" //
+            + "     * @param p8 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" //
+            + "            final Object p7, final Object p8) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6, p7, " //
+            + "p8);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param marker the marker data specific to this log statement%n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @param p7 parameter to the message.%n" //
+            + "     * @param p8 parameter to the message.%n" //
+            + "     * @param p9 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final Marker marker, final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" //
+            + "            final Object p7, final Object p8, final Object p9) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, message, p0, p1, p2, p3, p4, p5, p6, p7, " //
+            + "p8, p9);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
             + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" //
             + "     * the {@link Throwable} {@code t} passed as parameter.%n" //
             + "     * %n" //
@@ -372,6 +595,28 @@ public final class Generate {
             + "    }%n" //
             + "%n" //
             + "    /**%n" //
+            + "     * Logs a message CharSequence with the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message CharSequence to log.%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final CharSequence message) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, (Throwable) null);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a CharSequence at the {@code CUSTOM_LEVEL} level including the stack trace of%n" //
+            + "     * the {@link Throwable} {@code t} passed as parameter.%n" //
+            + "     * %n" //
+            + "     * @param message the CharSequence to log.%n" //
+            + "     * @param t the exception to log, including its stack trace.%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final CharSequence message, final Throwable t) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, t);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
             + "     * Logs a message object with the {@code CUSTOM_LEVEL} level.%n" //
             + "     * %n" //
             + "     * @param message the message object to log.%n" //
@@ -392,6 +637,192 @@ public final class Generate {
             + "    }%n" //
             + "%n" //
             + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @param p7 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" //
+            + "            final Object p7) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6, p7);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @param p7 parameter to the message.%n" //
+            + "     * @param p8 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" //
+            + "            final Object p7, final Object p8) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6, p7, " //
+            + "p8);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
+            + "     * Logs a message with parameters at the {@code CUSTOM_LEVEL} level.%n" //
+            + "     * %n" //
+            + "     * @param message the message to log; the format depends on the message factory.%n" //
+            + "     * @param p0 parameter to the message.%n" //
+            + "     * @param p1 parameter to the message.%n" //
+            + "     * @param p2 parameter to the message.%n" //
+            + "     * @param p3 parameter to the message.%n" //
+            + "     * @param p4 parameter to the message.%n" //
+            + "     * @param p5 parameter to the message.%n" //
+            + "     * @param p6 parameter to the message.%n" //
+            + "     * @param p7 parameter to the message.%n" //
+            + "     * @param p8 parameter to the message.%n" //
+            + "     * @param p9 parameter to the message.%n" //
+            + "     * @see #getMessageFactory()%n" //
+            + "     * @since Log4j-2.6%n" //
+            + "     */%n" //
+            + "    public void methodName(final String message, final Object p0, " //
+            + "final Object p1, final Object p2,%n" //
+            + "            final Object p3, final Object p4, final Object p5, final Object p6,%n" //
+            + "            final Object p7, final Object p8, final Object p9) {%n" //
+            + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, p0, p1, p2, p3, p4, p5, p6, p7, " //
+            + "p8, p9);%n" //
+            + "    }%n" //
+            + "%n" //
+            + "    /**%n" //
             + "     * Logs a message at the {@code CUSTOM_LEVEL} level including the stack trace of%n" //
             + "     * the {@link Throwable} {@code t} passed as parameter.%n" //
             + "     * %n" //
@@ -408,7 +839,7 @@ public final class Generate {
             + "     *%n" //
             + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" //
             + "     *            the format depends on the message factory.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Supplier<?> msgSupplier) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, (Throwable) null);%n" //
@@ -421,7 +852,7 @@ public final class Generate {
             + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" //
             + "     *            the format depends on the message factory.%n" //
             + "     * @param t the exception to log, including its stack trace.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Supplier<?> msgSupplier, final Throwable t) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, t);%n" //
@@ -434,7 +865,7 @@ public final class Generate {
             + "     * @param marker the marker data specific to this log statement%n" //
             + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" //
             + "     *            the format depends on the message factory.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Marker marker, final Supplier<?> msgSupplier) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, (Throwable) null);%n" //
@@ -448,7 +879,7 @@ public final class Generate {
             + "     * @param message the message to log; the format depends on the message factory.%n" //
             + "     * @param paramSuppliers An array of functions, which when called, produce the desired log" //
             + " message parameters.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Marker marker, final String message, final Supplier<?>..." //
             + " paramSuppliers) {%n" //
@@ -464,7 +895,7 @@ public final class Generate {
             + "     * @param msgSupplier A function, which when called, produces the desired log message;%n" //
             + "     *            the format depends on the message factory.%n" //
             + "     * @param t A Throwable or null.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Marker marker, final Supplier<?> msgSupplier, final Throwable t) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, t);%n" //
@@ -477,7 +908,7 @@ public final class Generate {
             + "     * @param message the message to log; the format depends on the message factory.%n" //
             + "     * @param paramSuppliers An array of functions, which when called, produce the desired log" //
             + " message parameters.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final String message, final Supplier<?>... paramSuppliers) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, message, paramSuppliers);%n" //
@@ -490,7 +921,7 @@ public final class Generate {
             + "     *%n" //
             + "     * @param marker the marker data specific to this log statement%n" //
             + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Marker marker, final MessageSupplier msgSupplier) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, marker, msgSupplier, (Throwable) null);%n" //
@@ -505,7 +936,7 @@ public final class Generate {
             + "     * @param marker the marker data specific to this log statement%n" //
             + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" //
             + "     * @param t A Throwable or null.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final Marker marker, final MessageSupplier msgSupplier, final " //
             + "Throwable t) {%n" //
@@ -518,7 +949,7 @@ public final class Generate {
             + "     * {@link MessageFactory} to construct the {@code Message}.%n"
             + "     *%n" //
             + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final MessageSupplier msgSupplier) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, (Throwable) null);%n" //
@@ -532,7 +963,7 @@ public final class Generate {
             + "     *%n" //
             + "     * @param msgSupplier A function, which when called, produces the desired log message.%n" //
             + "     * @param t the exception to log, including its stack trace.%n" //
-            + "     * @since 2.4%n" //
+            + "     * @since Log4j-2.4%n" //
             + "     */%n" //
             + "    public void methodName(final MessageSupplier msgSupplier, final Throwable t) {%n" //
             + "        logger.logIfEnabled(FQCN, CUSTOM_LEVEL, null, msgSupplier, t);%n" //
@@ -549,7 +980,7 @@ public final class Generate {
         /**
          * Generates source code for custom logger wrappers that only provide convenience methods for the specified
          * custom levels, not for the standard built-in levels.
-         * 
+         *
          * @param args className of the custom logger to generate, followed by a NAME=intLevel pair for each custom log
          *            level to generate convenience methods for
          */
@@ -570,7 +1001,7 @@ public final class Generate {
         /**
          * Generates source code for extended logger wrappers that provide convenience methods for the specified custom
          * levels.
-         * 
+         *
          * @param args className of the custom logger to generate, followed by a NAME=intLevel pair for each custom log
          *            level to generate convenience methods for
          */


[11/38] logging-log4j2 git commit: Fixing missing space typo.

Posted by rg...@apache.org.
Fixing missing space typo.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/6ef68fad
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/6ef68fad
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/6ef68fad

Branch: refs/heads/master
Commit: 6ef68fad21b378ffb7a118f4df6f23aa09941741
Parents: 0ad2b6d
Author: ggregory <gg...@apache.org>
Authored: Thu Apr 21 11:00:24 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 src/site/xdoc/manual/layouts.xml.vm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/6ef68fad/src/site/xdoc/manual/layouts.xml.vm
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/layouts.xml.vm b/src/site/xdoc/manual/layouts.xml.vm
index 714accd..83f2e57 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -541,7 +541,7 @@ WARN  [main]: Message 2</pre>
               </td>
               <td>
                 <p>Outputs the fully qualified class name of the caller issuing the logging request.
-                  This conversion specifier can be optionally followed by<em>precision specifier</em>, that
+                  This conversion specifier can be optionally followed by <em>precision specifier</em>, that
                   follows the same rules as the logger name converter.
                 </p>
                 <p>Generating the class name of the caller (<a href="#LocationInformation">location information</a>)


[23/38] logging-log4j2 git commit: LOG4J2-1342 added implementation of new method #memento(), ensure internal parameters field is not null

Posted by rg...@apache.org.
LOG4J2-1342 added implementation of new method #memento(), ensure internal parameters field is not null


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/710c34d6
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/710c34d6
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/710c34d6

Branch: refs/heads/master
Commit: 710c34d6cc4332b351ab818b0e1240b92613f26a
Parents: 185dce2
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:38:04 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/impl/MutableLogEvent.java     | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/710c34d6/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
index e256723..7fd31c0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -27,6 +27,7 @@ import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.apache.logging.log4j.message.ReusableMessage;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.util.Strings;
@@ -60,10 +61,11 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
     private ThreadContext.ContextStack contextStack;
 
     public MutableLogEvent() {
-        this(null);
+        this(new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE), new Object[10]);
     }
 
-    public MutableLogEvent(final Object[] replacementParameters) {
+    public MutableLogEvent(final StringBuilder msgText, final Object[] replacementParameters) {
+        this.messageText = msgText;
         this.parameters = replacementParameters;
     }
 
@@ -273,6 +275,15 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
     }
 
     @Override
+    public Message memento() {
+        if (message != null) {
+            return message;
+        }
+        Object[] params = parameters == null ? new Object[0] : Arrays.copyOf(parameters, parameterCount);
+        return new ParameterizedMessage(messageText.toString(), params);
+    }
+
+    @Override
     public Throwable getThrown() {
         return thrown;
     }


[32/38] logging-log4j2 git commit: LOG4J2-1373 added comment on @since versioning convention in generated code

Posted by rg...@apache.org.
LOG4J2-1373 added comment on @since versioning convention in generated code


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/be8779b9
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/be8779b9
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/be8779b9

Branch: refs/heads/master
Commit: be8779b9c8f2265f3cfe34229ee461261f40a71e
Parents: 31c76c7
Author: rpopma <rp...@apache.org>
Authored: Sat Apr 23 15:42:24 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 .../main/java/org/apache/logging/log4j/core/tools/Generate.java   | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/be8779b9/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
index c86004d..b1ca676 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/tools/Generate.java
@@ -44,6 +44,9 @@ import java.util.List;
  * DEFCON3=550}
  */
 public final class Generate {
+    // Implementation note:
+    // The generated code is in the user's namespace which has its own versioning scheme, so
+    // any @since tags in the generated code deliberately mention "Log4j-2.x" rather than just the log4j version number.
 
     static final String PACKAGE_DECLARATION = "package %s;%n%n";
 


[22/38] logging-log4j2 git commit: LOG4J2-1342 added implementation of new method #memento()

Posted by rg...@apache.org.
LOG4J2-1342 added implementation of new method #memento()


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/185dce26
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/185dce26
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/185dce26

Branch: refs/heads/master
Commit: 185dce2651653b8eb9923bed0ef4146305661476
Parents: d80793b
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:37:26 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../apache/logging/log4j/core/async/RingBufferLogEvent.java | 9 +++++++++
 1 file changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/185dce26/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index ab5e3d0..f687ff4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -31,6 +31,7 @@ import org.apache.logging.log4j.core.impl.ThrowableProxy;
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.ParameterizedMessage;
 import org.apache.logging.log4j.message.ReusableMessage;
 import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.message.TimestampMessage;
@@ -265,6 +266,14 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
         return parameterCount;
     }
 
+    @Override
+    public Message memento() {
+        if (message != null) {
+            return message;
+        }
+        Object[] params = parameters == null ? new Object[0] : Arrays.copyOf(parameters, parameterCount);
+        return new ParameterizedMessage(messageText.toString(), params);
+    }
 
     // CharSequence impl
 


[08/38] logging-log4j2 git commit: [LOG4J2-1372] XMLLayout indents, but not the first child tag (Event).

Posted by rg...@apache.org.
[LOG4J2-1372] XMLLayout indents, but not the first child tag (Event).


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/1d12bf0e
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/1d12bf0e
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/1d12bf0e

Branch: refs/heads/master
Commit: 1d12bf0e32c41597d8f4a138bea36d146a534126
Parents: f7909e2
Author: ggregory <gg...@apache.org>
Authored: Wed Apr 20 09:17:28 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:27 2016 -0700

----------------------------------------------------------------------
 .../log4j/core/layout/JacksonFactory.java       | 39 +++++++++-
 .../appender/XmlCompleteFileAppenderTest.java   | 82 ++++++++++++++++++++
 .../core/appender/XmlFileAppenderTest.java      |  1 +
 src/changes/changes.xml                         |  3 +
 4 files changed, 124 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
index 763f42a..3b34957 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
@@ -19,12 +19,15 @@ package org.apache.logging.log4j.core.layout;
 import java.util.HashSet;
 import java.util.Set;
 
+import javax.xml.stream.XMLStreamException;
+
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.jackson.JsonConstants;
 import org.apache.logging.log4j.core.jackson.Log4jJsonObjectMapper;
 import org.apache.logging.log4j.core.jackson.Log4jXmlObjectMapper;
 import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
 import org.apache.logging.log4j.core.jackson.XmlConstants;
+import org.codehaus.stax2.XMLStreamWriter2;
 
 import com.fasterxml.jackson.core.PrettyPrinter;
 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
@@ -72,6 +75,8 @@ abstract class JacksonFactory {
 
     static class XML extends JacksonFactory {
 
+        static final int DEFAULT_INDENT = 1;
+        
         @Override
         protected String getPropertNameForContextMap() {
             return XmlConstants.ELT_CONTEXT_MAP;
@@ -100,7 +105,7 @@ abstract class JacksonFactory {
 
         @Override
         protected PrettyPrinter newPrettyPrinter() {
-            return new DefaultXmlPrettyPrinter();
+            return new Log4jXmlPrettyPrinter(DEFAULT_INDENT);
         }
     }
 
@@ -137,6 +142,38 @@ abstract class JacksonFactory {
         }
     }
 
+    /**
+     * When &lt;Event&gt;s are written into a XML file; the "Event" object is not the root element, but an element named
+     * &lt;Events&gt; created using {@link #getHeader()} and {@link #getFooter()} methods.<br/>
+     * {@link com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter} is used to print the Event object into
+     * XML; hence it assumes &lt;Event&gt; tag as the root element, so it prints the &lt;Event&gt; tag without any
+     * indentation. To add an indentation to the &lt;Event&gt; tag; hence an additional indentation for any
+     * sub-elements, this class is written. As an additional task, to avoid the blank line printed after the ending
+     * &lt;/Event&gt; tag, {@link #writePrologLinefeed(XMLStreamWriter2)} method is also overridden.
+     */
+    static class Log4jXmlPrettyPrinter extends DefaultXmlPrettyPrinter {
+
+        private static final long serialVersionUID = 1L;
+
+        Log4jXmlPrettyPrinter(int nesting) {
+            _nesting = nesting;
+        }
+
+        @Override
+        public void writePrologLinefeed(XMLStreamWriter2 sw) throws XMLStreamException {
+            // nothing
+        }
+
+        /**
+         * Sets the nesting level to 1 rather than 0, so the "Event" tag will get indentation of next level below root.
+         */
+        @Override
+        public DefaultXmlPrettyPrinter createInstance() {
+            return new Log4jXmlPrettyPrinter(XML.DEFAULT_INDENT);
+        }
+
+    }
+
     abstract protected String getPropertNameForContextMap();
 
     abstract protected String getPropertNameForSource();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
index 344b221..2b7fc92 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlCompleteFileAppenderTest.java
@@ -57,6 +57,7 @@ public class XmlCompleteFileAppenderTest {
         try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
             line1 = reader.readLine();
             line2 = reader.readLine();
+            reader.readLine(); // ignore the empty line after the <Events> root
             line3 = reader.readLine();
             line4 = reader.readLine();
         } finally {
@@ -81,4 +82,85 @@ public class XmlCompleteFileAppenderTest {
         final String location = "testFlushAtEndOfBatch";
         assertTrue("no location", !line1.contains(location));
     }
+
+    /**
+     * Test the indentation of the Events XML.
+     * <p>Expected Events XML is as below.</p>
+     * <pre>
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;Events xmlns=&quot;http://logging.apache.org/log4j/2.0/events&quot;&gt;
+
+  &lt;Event xmlns=&quot;http://logging.apache.org/log4j/2.0/events&quot; timeMillis=&quot;1460974522088&quot; thread=&quot;main&quot; level=&quot;INFO&quot; loggerName=&quot;com.foo.Bar&quot; endOfBatch=&quot;false&quot; loggerFqcn=&quot;org.apache.logging.log4j.spi.AbstractLogger&quot; threadId=&quot;11&quot; threadPriority=&quot;5&quot;&gt;
+    &lt;Message&gt;First Msg tag must be in level 2 after correct indentation&lt;/Message&gt;
+  &lt;/Event&gt;
+
+  &lt;Event xmlns=&quot;http://logging.apache.org/log4j/2.0/events&quot; timeMillis=&quot;1460974522089&quot; thread=&quot;main&quot; level=&quot;INFO&quot; loggerName=&quot;com.foo.Bar&quot; endOfBatch=&quot;true&quot; loggerFqcn=&quot;org.apache.logging.log4j.spi.AbstractLogger&quot; threadId=&quot;11&quot; threadPriority=&quot;5&quot;&gt;
+    &lt;Message&gt;Second Msg tag must also be in level 2 after correct indentation&lt;/Message&gt;
+  &lt;/Event&gt;
+&lt;/Events&gt;
+     * </pre>
+     * @throws Exception
+     */
+    @Test
+    public void testChildElementsAreCorrectlyIndented() throws Exception {
+        final File file = new File("target", "XmlCompleteFileAppenderTest.log");
+        file.delete();
+        final Logger log = LogManager.getLogger("com.foo.Bar");
+        final String firstLogMsg = "First Msg tag must be in level 2 after correct indentation";
+        log.info(firstLogMsg);
+        final String secondLogMsg = "Second Msg tag must also be in level 2 after correct indentation";
+        log.info(secondLogMsg);
+        CoreLoggerContexts.stopLoggerContext(false, file); // stop async thread
+
+        String[] lines = new String[9];
+
+        try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+
+            int usefulLinesIndex = 0;
+            String readLine;
+            while((readLine = reader.readLine()) != null) {
+
+                if (!"".equals(readLine.trim())) {
+                    lines[usefulLinesIndex] = readLine;
+                    usefulLinesIndex++;
+                }
+            }
+        } finally {
+            file.delete();
+        }
+
+        String currentLine = lines[0];
+        assertFalse("line1 incorrect: [" + currentLine + "], must have no indentation", currentLine.startsWith(" "));
+        // <EVENTS
+        currentLine = lines[1];
+        assertFalse("line2 incorrect: [" + currentLine + "], must have no indentation", currentLine.startsWith(" "));
+        // <EVENT
+        currentLine = lines[2];
+        assertTrue("line3 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith("  "));
+        assertFalse("line3 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith("   "));
+        // <MSG
+        currentLine = lines[3];
+        assertTrue("line4 incorrect: [" + currentLine + "], must have four-space indentation", currentLine.startsWith("    "));
+        assertFalse("line4 incorrect: [" + currentLine + "], must not have more than four-space indentation", currentLine.startsWith("     "));
+        // </EVENT
+        currentLine = lines[4];
+        assertTrue("line5 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith("  "));
+        assertFalse("line5 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith("   "));
+
+        // <EVENT
+        currentLine = lines[5];
+        assertTrue("line6 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith("  "));
+        assertFalse("line6 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith("   "));
+        // <MSG
+        currentLine = lines[6];
+        assertTrue("line7 incorrect: [" + currentLine + "], must have four-space indentation", currentLine.startsWith("    "));
+        assertFalse("line7 incorrect: [" + currentLine + "], must not have more than four-space indentation", currentLine.startsWith("     "));
+        // </EVENT
+        currentLine = lines[7];
+        assertTrue("line8 incorrect: [" + currentLine + "], must have two-space indentation", currentLine.startsWith("  "));
+        assertFalse("line8 incorrect: [" + currentLine + "], must not have more than two-space indentation", currentLine.startsWith("   "));
+        // </EVENTS
+        currentLine = lines[8];
+        assertFalse("line9 incorrect: [" + currentLine + "], must have no indentation", currentLine.startsWith(" "));
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
index b509b30..c3c04d8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/XmlFileAppenderTest.java
@@ -54,6 +54,7 @@ public class XmlFileAppenderTest {
         String line2;
         String line3;
         try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            reader.readLine(); // first line is empty, so ignore it
             line1 = reader.readLine();
             line2 = reader.readLine();
             line3 = reader.readLine();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/1d12bf0e/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index cb717ed..0edfea6 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,9 @@
   </properties>
   <body>
     <release version="2.6" date="2016-MM-DD" description="GA Release 2.6">
+      <action issue="LOG4J2-1372" dev="rgoers" type="fix" due-to="Kamal Mettananda, Gary Gregory">
+        XMLLayout indents, but not the first child tag (Event).
+      </action>
       <action issue="LOG4J2-1363" dev="rgoers" type="fix">
         Properties Configuration did not support includeLocation attribute on Loggers.
       </action>


[13/38] logging-log4j2 git commit: Fixing missing space typo.

Posted by rg...@apache.org.
Fixing missing space typo.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/0ad2b6d0
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/0ad2b6d0
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/0ad2b6d0

Branch: refs/heads/master
Commit: 0ad2b6d0f95b18674628949365c6ee8931c0cf9a
Parents: 8dd1868
Author: ggregory <gg...@apache.org>
Authored: Thu Apr 21 11:00:08 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 src/site/xdoc/manual/layouts.xml.vm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/0ad2b6d0/src/site/xdoc/manual/layouts.xml.vm
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/layouts.xml.vm b/src/site/xdoc/manual/layouts.xml.vm
index ae4c1a0..714accd 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -490,7 +490,7 @@ WARN  [main]: Message 2</pre>
               </td>
               <td>
                 <p>Outputs the name of the logger that published the logging event. The logger conversion
-                  specifier can be optionally followed by<em>precision specifier</em>, which consists of a
+                  specifier can be optionally followed by <em>precision specifier</em>, which consists of a
                   decimal integer, or a pattern starting with a decimal integer.
                 </p>
                 <p>If a precision specifier is given and it is an integer value, then only the corresponding number


[37/38] logging-log4j2 git commit: Adding README.md file for GitHub

Posted by rg...@apache.org.
Adding README.md file for GitHub


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/bf3ef615
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/bf3ef615
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/bf3ef615

Branch: refs/heads/master
Commit: bf3ef615ba165d26cd2ef556546830ce3c5a9d4c
Parents: fd01615
Author: Mikael Ståldal <mi...@magine.com>
Authored: Mon Apr 25 18:10:14 2016 +0200
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:31 2016 -0700

----------------------------------------------------------------------
 README.md | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bf3ef615/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d399485
--- /dev/null
+++ b/README.md
@@ -0,0 +1,20 @@
+# Apache Log4j 2
+
+Apache Log4j 2 is an upgrade to Log4j that provides significant improvements over its predecessor, Log4j 1.x,
+and provides many of the improvements available in Logback while fixing some inherent problems in Logback's architecture.
+
+## Documentation
+
+The Log4j 2 User's Guide is available [here](http://logging.apache.org/log4j/2.x/manual/index.html) or as a downloadable
+[PDF](http://logging.apache.org/log4j/2.x/log4j-users-guide.pdf).
+
+## Requirements
+
+Log4j 2.4 and greater requires Java 7, versions 2.0-alpha1 to 2.3 required Java 6.
+Some features require optional dependencies; the documentation for these features specifies the dependencies.
+
+## License
+
+Apache Log4j 2 is distributed under the [Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html).
+
+


[06/38] logging-log4j2 git commit: javadoc

Posted by rg...@apache.org.
javadoc


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/9159e846
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/9159e846
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/9159e846

Branch: refs/heads/master
Commit: 9159e84675699923505cecd11399f4f9bcad73eb
Parents: 287d2c6
Author: rpopma <rp...@apache.org>
Authored: Thu Apr 21 14:22:02 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:27 2016 -0700

----------------------------------------------------------------------
 .../log4j/core/async/perftest/IdleStrategy.java | 24 +-------------------
 .../core/async/perftest/NoOpIdleStrategy.java   |  7 ++++--
 2 files changed, 6 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9159e846/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IdleStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IdleStrategy.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IdleStrategy.java
index eca115c..65b97df 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IdleStrategy.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/IdleStrategy.java
@@ -19,11 +19,6 @@ package org.apache.logging.log4j.core.async.perftest;
 /**
  * Idle strategy for use by threads when they do not have work to do.
  *
- * <h3>Note regarding implementor state</h3>
- *
- * Some implementations are known to be stateful, please note that you cannot safely assume implementations to be stateless.
- * Where implementations are stateful it is recommended that implementation state is padded to avoid false sharing.
- *
  * <h3>Note regarding potential for TTSP(Time To Safe Point) issues</h3>
  *
  * If the caller spins in a 'counted' loop, and the implementation does not include a a safepoint poll this may cause a TTSP
@@ -36,24 +31,7 @@ package org.apache.logging.log4j.core.async.perftest;
  */
 interface IdleStrategy {
     /**
-     * Perform current idle action (e.g. nothing/yield/sleep). To be used in conjunction with {@link IdleStrategy#reset()}
-     * to clear internal state when idle period is over (or before it begins). Callers are expected to follow this pattern:
-     *
-     * <pre>
-     * <code>while (isRunning) {
-     *   if (!hasWork()) {
-     *     idleStrategy.reset();
-     *     while (!hasWork()) {
-     *       if (!isRunning) {
-     *         return;
-     *       }
-     *       idleStrategy.idle();
-     *     }
-     *   }
-     *   doWork();
-     * }
-     * </code>
-     * </pre>
+     * Perform current idle action (e.g. nothing/yield/sleep).
      */
     void idle();
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/9159e846/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/NoOpIdleStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/NoOpIdleStrategy.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/NoOpIdleStrategy.java
index ad5d280..6bce312 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/NoOpIdleStrategy.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/NoOpIdleStrategy.java
@@ -17,8 +17,11 @@
 package org.apache.logging.log4j.core.async.perftest;
 
 /**
- * Low-latency idle strategy to be employed in loops that do significant work on each iteration such that any work in the
- * idle strategy would be wasteful.
+ * No operation idle strategy.
+ * <p>
+ * This idle strategy should be prevented from being inlined by using a Hotspot compiler command as a JVM argument e.g:
+ * <code>-XX:CompileCommand=dontinline,org.apache.logging.log4j.core.async.perftest.NoOpIdleStrategy::idle</code>
+ * </p>
  */
 class NoOpIdleStrategy implements IdleStrategy {
 


[35/38] logging-log4j2 git commit: LOG4J2-1297 improve instructions on how to run this test

Posted by rg...@apache.org.
LOG4J2-1297 improve instructions on how to run this test


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/fd01615c
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/fd01615c
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/fd01615c

Branch: refs/heads/master
Commit: fd01615c2fc7c8dedcb7d87651a2308ab8bef8e3
Parents: fdaefaa
Author: rpopma <rp...@apache.org>
Authored: Tue Apr 26 00:40:23 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:31 2016 -0700

----------------------------------------------------------------------
 .../apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java    | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fd01615c/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
index 5fbac7e..daccb12 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
@@ -39,7 +39,10 @@ import org.slf4j.LoggerFactory;
  * for each uses a FileAppender
  */
 // HOW TO RUN THIS TEST
-// java -jar target/benchmarks.jar ".*FileAppenderBenchmark.*" -f 1 -i 5 -wi 5 -bm sample -tu ns
+// java -jar log4j-perf/target/benchmarks.jar ".*FileAppenderBenchmark.*" -f 1 -wi 10 -i 20
+//
+// RUNNING THIS TEST WITH 4 THREADS:
+// java -jar log4j-perf/target/benchmarks.jar ".*FileAppenderBenchmark.*" -f 1 -wi 10 -i 20 -t 4
 @State(Scope.Thread)
 public class FileAppenderBenchmark {
     public static final String MESSAGE = "This is a debug message";


[30/38] logging-log4j2 git commit: Useful toString().

Posted by rg...@apache.org.
Useful toString().


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/bb534792
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/bb534792
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/bb534792

Branch: refs/heads/master
Commit: bb534792de01003c8344a39e9f6f07b1517980bf
Parents: 67070d3
Author: ggregory <gg...@apache.org>
Authored: Thu Apr 21 23:09:15 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 .../java/org/apache/logging/log4j/junit/CleanFiles.java     | 9 +++++++++
 1 file changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bb534792/log4j-core/src/test/java/org/apache/logging/log4j/junit/CleanFiles.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/junit/CleanFiles.java b/log4j-core/src/test/java/org/apache/logging/log4j/junit/CleanFiles.java
index 6c0ac76..00615b8 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/junit/CleanFiles.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/junit/CleanFiles.java
@@ -67,4 +67,13 @@ public class CleanFiles extends ExternalResource {
     protected void after() {
         this.clean();
     }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("CleanFiles [");
+        builder.append(files);
+        builder.append("]");
+        return builder.toString();
+    }
 }


[12/38] logging-log4j2 git commit: added comments

Posted by rg...@apache.org.
added comments


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/8dd1868a
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/8dd1868a
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/8dd1868a

Branch: refs/heads/master
Commit: 8dd1868ac9b941b8681059f47d279712e38790e8
Parents: d816108
Author: rpopma <rp...@apache.org>
Authored: Thu Apr 21 14:42:30 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 .../core/async/perftest/SimpleLatencyTest.java     | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8dd1868a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
index 8665d5d..ff2de75 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
@@ -45,6 +45,7 @@ public class SimpleLatencyTest {
         final int threadCount = Integer.parseInt(args[0]);
         final int intervalMicros = Integer.parseInt(args[1]);
 
+        // print to console if ringbuffer is full
         System.setProperty("log4j2.AsyncEventRouter", PrintingDefaultAsyncEventRouter.class.getName());
         System.setProperty("AsyncLogger.RingBufferSize", String.valueOf(256 * 1024));
         System.setProperty("Log4jContextSelector", AsyncLoggerContextSelector.class.getName());
@@ -60,6 +61,7 @@ public class SimpleLatencyTest {
         final long interval = TimeUnit.MICROSECONDS.toNanos(intervalMicros);// * threadCount;
         System.out.printf("%d threads, interval is %d nanos%n", threadCount, interval);
 
+        // Warmup: run as many iterations of 50,000 calls to logger.log as we can in 1 minute
         final long WARMUP_DURATION_MILLIS = TimeUnit.MINUTES.toMillis(1);
         List<Histogram> warmupHistograms = new ArrayList<>(threadCount);
 
@@ -69,6 +71,7 @@ public class SimpleLatencyTest {
         System.out.println("Warmup done.");
         Thread.sleep(1000);
 
+        // Actual test: run as many iterations of 5,000,000 calls to logger.log as we can in 4 minutes.
         long start = System.currentTimeMillis();
         List<Histogram> histograms = new ArrayList<>(threadCount);
 
@@ -77,6 +80,7 @@ public class SimpleLatencyTest {
         runLatencyTest(logger, TEST_DURATION_MILLIS, COUNT, interval, idleStrategy, histograms, nanoTimeCost, threadCount);
         long end = System.currentTimeMillis();
 
+        // ... and report the results
         final Histogram result = new Histogram(TimeUnit.SECONDS.toNanos(10), 3);
         for (Histogram hist : histograms) {
             result.add(hist);
@@ -86,9 +90,8 @@ public class SimpleLatencyTest {
     }
 
     public static void runLatencyTest(final Logger logger, final long durationMillis, final int samples,
-            final long intervalNanos,
-            final IdleStrategy idleStrategy, final List<Histogram> histograms, final long nanoTimeCost,
-            final int threadCount) throws InterruptedException {
+            final long intervalNanos, final IdleStrategy idleStrategy, final List<Histogram> histograms,
+            final long nanoTimeCost, final int threadCount) throws InterruptedException {
 
         Thread[] threads = new Thread[threadCount];
         final CountDownLatch LATCH = new CountDownLatch(threadCount);
@@ -100,9 +103,9 @@ public class SimpleLatencyTest {
                 public void run() {
                     LATCH.countDown();
                     try {
-                        LATCH.await();
+                        LATCH.await(); // wait until all threads are ready to go
                     } catch (InterruptedException e) {
-                        interrupt(); // restore interrupt status
+                        interrupt();
                         return;
                     }
                     long start = System.currentTimeMillis();
@@ -118,7 +121,9 @@ public class SimpleLatencyTest {
         }
     }
 
-    private static void runLatencyTest(int samples, Logger logger, long nanoTimeCost, Histogram hist, long intervalNanos, IdleStrategy idleStrategy) {
+    private static void runLatencyTest(int samples, Logger logger, long nanoTimeCost, Histogram hist,
+            long intervalNanos, IdleStrategy idleStrategy) {
+
         for (int i = 0; i < samples; i++) {
             final long s1 = System.nanoTime();
             logger.info(LATENCY_MSG);


[09/38] logging-log4j2 git commit: LOG4J2-1342 use more reliable CountDownLatch to ensure background thread is finished

Posted by rg...@apache.org.
LOG4J2-1342 use more reliable CountDownLatch to ensure background thread is finished


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/b2e90dc4
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/b2e90dc4
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/b2e90dc4

Branch: refs/heads/master
Commit: b2e90dc40cfa7789b960f76fc853c1ab79fe8422
Parents: 047202a
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:24:00 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/layout/CsvParameterLayoutTest.java   | 9 +++++----
 .../apache/logging/log4j/test/appender/ListAppender.java    | 6 ++++++
 2 files changed, 11 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2e90dc4/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
index ce3abfc..a51db99 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
@@ -21,6 +21,8 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.commons.csv.CSVFormat;
 import org.apache.logging.log4j.Level;
@@ -97,6 +99,8 @@ public class CsvParameterLayoutTest {
         final ListAppender appender = new ListAppender("List", null, layout, true, false);
         appender.start();
 
+        appender.countDownLatch = new CountDownLatch(4);
+
         // set appender on root and set level to debug
         root.addAppender(appender);
         root.setLevel(Level.DEBUG);
@@ -109,10 +113,7 @@ public class CsvParameterLayoutTest {
         }
 
         // wait until background thread finished processing
-        int maxTries = 50;
-        while (appender.getMessages().size() < 4 && maxTries-- > 0) {
-            Thread.sleep(1L);
-        }
+        appender.countDownLatch.await(10, TimeUnit.SECONDS);
         assertEquals("Background thread did not finish processing: msg count", 4, appender.getMessages().size());
 
         // don't stop appender until background thread is done

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/b2e90dc4/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
index 19aeaee..acab7c1 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
@@ -20,6 +20,7 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.CountDownLatch;
 
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.Layout;
@@ -60,6 +61,8 @@ public class ListAppender extends AbstractAppender {
 
     private static final String WINDOWS_LINE_SEP = "\r\n";
 
+    public CountDownLatch countDownLatch = null;
+
     public ListAppender(final String name) {
         super(name, null, null);
         newLine = false;
@@ -99,6 +102,9 @@ public class ListAppender extends AbstractAppender {
         } else {
             write(layout.toByteArray(event));
         }
+        if (countDownLatch != null) {
+            countDownLatch.countDown();
+        }
     }
 
     void write(final byte[] bytes) {


[38/38] logging-log4j2 git commit: Merge branch 'LOG4j2-494'

Posted by rg...@apache.org.
Merge branch 'LOG4j2-494'


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/988ed509
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/988ed509
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/988ed509

Branch: refs/heads/master
Commit: 988ed509361431028045bfeb269fa6408333d7d7
Parents: 2d16d34 bf3ef61
Author: Ralph Goers <rg...@nextiva.com>
Authored: Mon Apr 25 22:33:42 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 22:33:42 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/status/StatusLogger.java      |   6 +
 .../apache/logging/log4j/util/LoaderUtil.java   |   8 +-
 log4j-core/${filename}                          |   0
 .../core/config/AbstractConfiguration.java      |  26 +-
 .../log4j/core/config/ConfigurationFactory.java |  66 +++--
 .../log4j/core/config/ConfigurationSource.java  |  51 +++-
 .../core/config/ConfiguratonFileWatcher.java    |   4 +
 .../logging/log4j/core/config/Configurator.java |  46 +++-
 .../builder/api/ConfigurationBuilder.java       |  17 ++
 .../impl/DefaultConfigurationBuilder.java       |  16 +-
 .../composite/CompositeConfiguration.java       | 183 +++++++++++++
 .../config/composite/DefaultMergeStrategy.java  | 266 +++++++++++++++++++
 .../core/config/composite/MergeStrategy.java    |  41 +++
 .../core/config/composite/package-info.java     |  21 ++
 .../properties/PropertiesConfiguration.java     |   2 +-
 .../PropertiesConfigurationBuilder.java         |   9 +-
 .../core/config/status/StatusConfiguration.java |   1 +
 .../log4j/core/impl/Log4jContextFactory.java    |  43 ++-
 .../logging/log4j/core/util/WatchManager.java   |   9 +
 .../core/config/CompositeConfigurationTest.java | 176 ++++++++++++
 .../log4j/core/config/TestConfigurator.java     |  11 +-
 .../src/test/resources/log4j-comp-appender.json |  34 +++
 .../src/test/resources/log4j-comp-appender.xml  |  39 +++
 .../src/test/resources/log4j-comp-filter.json   |   9 +
 .../src/test/resources/log4j-comp-filter.xml    |  34 +++
 .../src/test/resources/log4j-comp-logger.json   |  36 +++
 .../src/test/resources/log4j-comp-logger.xml    |  41 +++
 .../test/resources/log4j-comp-properties.json   |  16 ++
 .../test/resources/log4j-comp-properties.xml    |  34 +++
 .../resources/log4j-comp-reconfig.properties    |  59 ++++
 .../src/test/resources/log4j-comp-reconfig.xml  |  39 +++
 pom.xml                                         |   2 +-
 src/site/site.xml                               |   1 +
 src/site/xdoc/manual/configuration.xml.vm       |  46 +++-
 34 files changed, 1332 insertions(+), 60 deletions(-)
----------------------------------------------------------------------



[26/38] logging-log4j2 git commit: LOG4J2-1297 added initial performance test results: synchronous logging throughput

Posted by rg...@apache.org.
LOG4J2-1297 added initial performance test results: synchronous logging throughput


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/7730ae5e
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/7730ae5e
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/7730ae5e

Branch: refs/heads/master
Commit: 7730ae5eed9b7296e38b9d60578365d2cae9e39b
Parents: f226b97
Author: rpopma <rp...@apache.org>
Authored: Mon Apr 25 23:44:10 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 .../garbage-free2.6-SyncThroughputLinux.png     | Bin 0 -> 70039 bytes
 src/site/xdoc/manual/garbagefree.xml            |  30 +++++++++++++++----
 2 files changed, 25 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7730ae5e/src/site/resources/images/garbage-free2.6-SyncThroughputLinux.png
----------------------------------------------------------------------
diff --git a/src/site/resources/images/garbage-free2.6-SyncThroughputLinux.png b/src/site/resources/images/garbage-free2.6-SyncThroughputLinux.png
new file mode 100644
index 0000000..5de5d9f
Binary files /dev/null and b/src/site/resources/images/garbage-free2.6-SyncThroughputLinux.png differ

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/7730ae5e/src/site/xdoc/manual/garbagefree.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/garbagefree.xml b/src/site/xdoc/manual/garbagefree.xml
index 66cd532..c9e8692 100644
--- a/src/site/xdoc/manual/garbagefree.xml
+++ b/src/site/xdoc/manual/garbagefree.xml
@@ -352,12 +352,32 @@ public void garbageFree() {
       </subsection>
       <a name="Performance" />
       <subsection name="Performance">
-
         <a name="Latency" />
-        <h4>TBD what to include here</h4>
-        <p>Async Loggers 2.5 vs 2.6 in garbage-free mode</p>
-        <p>Log4j 2.6 synchronous logging "classic" versus garbage-free mode - impact of adding threads</p>
-        <p>Comparison with other logging libraries?</p>
+        <h4>Response Time of Garbage-free Logging is Consistently Better with Fewer Spikes</h4>
+        <p>TODO: add latency histogram: Response time distribution of Async Loggers 2.5 vs 2.6 in garbage-free mode under various loads.</p>
+        <p>TODO: add latency histogram: Response time distribution of synchronous logging vs 2.6 in garbage-free mode under various loads.</p>
+
+        <a name="Throughput" />
+        <h4>Throughput of Garbage-free Logging May Be Worse (But It's All Relative)</h4>
+        <p>Log4j 2.6 in garbage-free mode has the highest throughput in single-threaded scenarios. In multi-threaded
+          scenarios,  Log4j 2.6 "classic" has highest throughput, with Log4j 2.6 in garbage-free mode and Log4j 2.5
+          not far behind. Our test results suggest that the throughput of all other logging frameworks rapidly
+          declines in multi-threaded applications.</p>
+        <p>The graph below compares Log4j 2.6 in garbage-free mode to Log4j 2.6 "classic" mode (which allocates
+          temporary objects for every logging call), Log4j 2.5, Log4j 1.2.17, Logback 1.1.7 and
+          Java util logging (JUL) on Oracle Java 1.8.0_45. All Log4j 2.x results use the RandomAccessFile appender.
+          Log4j 1.2.17, Logback and JUL use their respective File appenders. ImmediateFlush was set to <tt>false</tt> for all
+          loggers that support this. The JUL results are for the <tt>XMLFormatter</tt> (which in our measurements was
+          about twice as fast as the <tt>SimpleFormatter</tt>).</p>
+        <p>The synchronous logging throughput results below are generated with the
+          <a href="http://openjdk.java.net/projects/code-tools/jmh/">JMH</a> Java benchmark harness.
+          See the <tt>org.apache.logging.log4j.perf.jmh.FileAppenderBenchmark</tt> source code in the log4j-perf module.</p>
+        <p><img src="../images/garbage-free2.6-SyncThroughputLinux.png"
+            alt="Throughput of Log4j 2.6 in garbage-free mode is slightly worse than in classic mode, but on par with 2.5 and much better than alternatives logging libraries" /></p>
+        <p>(TODO: DOUBLE-CHECK) The above results are for <em>synchronous</em> logging. For <em>asynchronous</em> logging,
+          there was no measurable difference in throughput between
+          Log4j 2.6 in garbage-free mode and Log4j 2.6 in "classic" mode (allocating
+          new objects on every logging call).</p>
       </subsection>
       <a name="UnderTheHood" />
       <subsection name="Under the Hood">


[33/38] logging-log4j2 git commit: LOG4J2-1374 & LOG4J2-1375: Migrate tests from Logback 1.1.3 to 1.1.7, Update SLF4J from 1.7.13 to 1.7.21

Posted by rg...@apache.org.
LOG4J2-1374 & LOG4J2-1375: Migrate tests from Logback 1.1.3 to 1.1.7, Update SLF4J from 1.7.13 to 1.7.21


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/66cc0c83
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/66cc0c83
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/66cc0c83

Branch: refs/heads/master
Commit: 66cc0c839101424fc7c79659d9abf4c402c871a6
Parents: 2db215b
Author: rpopma <rp...@apache.org>
Authored: Sat Apr 23 20:12:12 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 pom.xml                 | 4 ++--
 src/changes/changes.xml | 6 ++++++
 2 files changed, 8 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/66cc0c83/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index df4140d..8815982 100644
--- a/pom.xml
+++ b/pom.xml
@@ -187,8 +187,8 @@
     <!-- <Log4jReleaseManager>Matt Sicker</Log4jReleaseManager>
     <Log4jReleaseKey>FA1C814D</Log4jReleaseKey> -->
     <!-- note that any properties you want available in velocity templates must not use periods! -->
-    <slf4jVersion>1.7.13</slf4jVersion>
-    <logbackVersion>1.1.3</logbackVersion>
+    <slf4jVersion>1.7.21</slf4jVersion>
+    <logbackVersion>1.1.7</logbackVersion>
     <jackson1Version>1.9.13</jackson1Version>
     <jackson2Version>2.7.3</jackson2Version>
     <springVersion>3.2.13.RELEASE</springVersion>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/66cc0c83/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 4c23f35..c5831c0 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,12 @@
   </properties>
   <body>
     <release version="2.6" date="2016-MM-DD" description="GA Release 2.6">
+      <action issue="LOG4J2-1375" dev="rpopma" type="update">
+        Update SLF4J from 1.7.13 to 1.7.21.
+      </action>
+      <action issue="LOG4J2-1374" dev="rpopma" type="update">
+        Migrate tests from Logback 1.1.3 to 1.1.7.
+      </action>
       <action issue="LOG4J2-1373" dev="rpopma" type="add">
         (GC) Update Logger wrapper Generator tool to generate methods for the new Logger methods.
       </action>


[24/38] logging-log4j2 git commit: LOG4J2-1334 enable unit tests that verify that synchronous logging and mixed sync/async is garbage-free

Posted by rg...@apache.org.
LOG4J2-1334	enable unit tests that verify that synchronous logging and mixed sync/async is garbage-free


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/bc81c74b
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/bc81c74b
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/bc81c74b

Branch: refs/heads/master
Commit: bc81c74b96925baf13dd34f5d4ac3776b6e3387b
Parents: 22e98d6
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:54:53 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java  | 2 --
 .../apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java    | 2 --
 2 files changed, 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bc81c74b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
index b917f93..c18861b 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeMixedSyncAyncLoggingTest.java
@@ -26,8 +26,6 @@ import org.junit.Test;
  */
 public class GcFreeMixedSyncAyncLoggingTest {
 
-    // Ignore until mixed synchronous/asynchronous logging is gc-free
-    @Ignore
     @Test
     public void testNoAllocationDuringSteadyStateLogging() throws Throwable {
         GcFreeLoggingTestUtil.runTest(getClass());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/bc81c74b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
index 9a01c22..731c2af 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/GcFreeSynchronousLoggingTest.java
@@ -26,8 +26,6 @@ import org.junit.Test;
  */
 public class GcFreeSynchronousLoggingTest {
 
-    // Ignore until synchronous logging is gc-free
-    @Ignore
     @Test
     public void testNoAllocationDuringSteadyStateLogging() throws Throwable {
         GcFreeLoggingTestUtil.runTest(getClass());


[25/38] logging-log4j2 git commit: LOG4J2-1342 MutableLogEvent.getMessage() returns this log event if message is not set

Posted by rg...@apache.org.
LOG4J2-1342 MutableLogEvent.getMessage() returns this log event if message is not set


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/c1729958
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/c1729958
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/c1729958

Branch: refs/heads/master
Commit: c17299589cdf16f8680323dd5d2c58f7530af85b
Parents: 710c34d
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:38:49 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../org/apache/logging/log4j/core/impl/MutableLogEventTest.java  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/c1729958/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
index 40e13e8..8f7b4ef 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/MutableLogEventTest.java
@@ -102,7 +102,7 @@ public class MutableLogEventTest {
         assertNull("fqcn", mutable.getLoggerFqcn());
         assertNull("logger", mutable.getLoggerName());
         assertNull("marker", mutable.getMarker());
-        assertEquals("msg", new SimpleMessage(Strings.EMPTY), mutable.getMessage());
+        assertEquals("msg", mutable, mutable.getMessage());
         assertEquals("nanoTm", 0, mutable.getNanoTime());
         assertEquals("tid", 0, mutable.getThreadId());
         assertNull("tname", mutable.getThreadName());
@@ -155,7 +155,7 @@ public class MutableLogEventTest {
         assertNull("fqcn", mutable.getLoggerFqcn());
         assertNull("logger", mutable.getLoggerName());
         assertNull("marker", mutable.getMarker());
-        assertEquals("msg", new SimpleMessage(Strings.EMPTY), mutable.getMessage());
+        assertEquals("msg", mutable, mutable.getMessage());
         assertNull("thrwn", mutable.getThrown());
 
         assertNull("source", mutable.getSource());


[05/38] logging-log4j2 git commit: cleanup

Posted by rg...@apache.org.
cleanup


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/02cb0fd9
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/02cb0fd9
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/02cb0fd9

Branch: refs/heads/master
Commit: 02cb0fd9ef474a5a23add027dc916d6da5c51296
Parents: 9159e84
Author: rpopma <rp...@apache.org>
Authored: Thu Apr 21 14:23:18 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:27 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/async/perftest/SimpleLatencyTest.java | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/02cb0fd9/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
index 73e7138..cad4e55 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
@@ -85,13 +85,6 @@ public class SimpleLatencyTest {
         final long nanoTimeCost = PerfTest.calcNanoTimeCost();
         System.out.println("nanoTimeCost=" + nanoTimeCost);
 
-//        long maxOpsPerSec = 1000 * 1000; // just assume... TODO make parameter
-//
-//        long oneOpDurationNanos = TimeUnit.SECONDS.toNanos(1) / maxOpsPerSec;
-//        long idleTimeNanos = (long) ((1.0 - targetLoadLevel) * oneOpDurationNanos);
-//        idleTimeNanos *= 10;
-//        System.out.printf("Idle time is %d nanos at %,f load level%n", idleTimeNanos, targetLoadLevel);
-
         final long interval = TimeUnit.MICROSECONDS.toNanos(intervalMicros);// * threadCount;
         System.out.printf("%d threads, interval is %d nanos%n", threadCount, interval);
 
@@ -101,6 +94,7 @@ public class SimpleLatencyTest {
         final int WARMUP_COUNT = 50000 / threadCount;
         final IdleStrategy idleStrategy = new YieldIdleStrategy();
         runLatencyTest(logger, WARMUP_DURATION_MILLIS, WARMUP_COUNT, interval, idleStrategy, warmupHistograms, nanoTimeCost, threadCount);
+        System.out.println("Warmup done.");
         Thread.sleep(1000);
 
         long start = System.currentTimeMillis();


[29/38] logging-log4j2 git commit: Useful toString(), especially when you use the Eclipse JUnit view.

Posted by rg...@apache.org.
Useful toString(), especially when you use the Eclipse JUnit view.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/67070d39
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/67070d39
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/67070d39

Branch: refs/heads/master
Commit: 67070d393bd6ea427a6d7748622b7737ab529a9a
Parents: bc81c74
Author: ggregory <gg...@apache.org>
Authored: Thu Apr 21 23:08:36 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 .../apache/logging/log4j/junit/LoggerContextRule.java    | 11 +++++++++++
 1 file changed, 11 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/67070d39/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
index 5bbda4f..59e921d 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/junit/LoggerContextRule.java
@@ -204,4 +204,15 @@ public class LoggerContextRule implements TestRule {
         }
         throw new AssertionError("No ListAppender named " + name + " found.");
     }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("LoggerContextRule [configLocation=");
+        builder.append(configLocation);
+        builder.append(", contextSelectorClass=");
+        builder.append(contextSelectorClass);
+        builder.append("]");
+        return builder.toString();
+    }
 }


[19/38] logging-log4j2 git commit: LOG4J2-1342 added implementation of new method #memento()

Posted by rg...@apache.org.
LOG4J2-1342 added implementation of new method #memento()


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/d80793b3
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/d80793b3
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/d80793b3

Branch: refs/heads/master
Commit: d80793b35721855d5f03eeb0b5706e64f4469a84
Parents: 8f3c146
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:37:07 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../org/apache/logging/log4j/message/ReusableObjectMessage.java | 5 +++++
 .../logging/log4j/message/ReusableParameterizedMessage.java     | 5 +++++
 .../org/apache/logging/log4j/message/ReusableSimpleMessage.java | 5 +++++
 3 files changed, 15 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d80793b3/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
index 920eff4..fddc0eb 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
@@ -110,4 +110,9 @@ public class ReusableObjectMessage implements ReusableMessage {
     public short getParameterCount() {
         return 0;
     }
+
+    @Override
+    public Message memento() {
+        return new ObjectMessage(obj);
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d80793b3/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index 12f4346..24c0e7d 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -76,6 +76,11 @@ public class ReusableParameterizedMessage implements ReusableMessage {
         return (short) argCount;
     }
 
+    @Override
+    public Message memento() {
+        return new ParameterizedMessage(messagePattern, getTrimmedParams());
+    }
+
     private void init(final String messagePattern, final int argCount, final Object[] paramArray) {
         this.varargs = null;
         this.messagePattern = messagePattern;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d80793b3/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
index 9fae16c..d894ef7 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
@@ -80,6 +80,11 @@ public class ReusableSimpleMessage implements ReusableMessage, CharSequence {
         return 0;
     }
 
+    @Override
+    public Message memento() {
+        return new SimpleMessage(charSequence);
+    }
+
     // CharSequence impl
 
     @Override


[28/38] logging-log4j2 git commit: LOG4J2-1297 throughput test improvements (added JUL, separated parameterized message from simple string logging)

Posted by rg...@apache.org.
LOG4J2-1297 throughput test improvements (added JUL, separated parameterized message from simple string logging)


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/f226b972
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f226b972
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f226b972

Branch: refs/heads/master
Commit: f226b97225030a4dca658d5f7cd52b50aa21a721
Parents: 66cc0c8
Author: rpopma <rp...@apache.org>
Authored: Sun Apr 24 22:58:37 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 .../log4j/perf/jmh/FileAppenderBenchmark.java   |  92 +++++-----
 .../perf/jmh/FileAppenderParamsBenchmark.java   | 170 +++++++++++++++++++
 2 files changed, 210 insertions(+), 52 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f226b972/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
index 9bea11e..5fbac7e 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderBenchmark.java
@@ -17,6 +17,11 @@
 
 package org.apache.logging.log4j.perf.jmh;
 
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.openjdk.jmh.annotations.Benchmark;
@@ -29,43 +34,41 @@ import org.openjdk.jmh.annotations.State;
 import org.openjdk.jmh.annotations.TearDown;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.util.concurrent.TimeUnit;
-
 /**
- * Benchmarks Log4j 2, Log4j 1, and Logback using the DEBUG level which is enabled for this test. The configuration
+ * Benchmarks Log4j 2, Log4j 1, Logback and JUL using the DEBUG level which is enabled for this test. The configuration
  * for each uses a FileAppender
  */
 // HOW TO RUN THIS TEST
 // java -jar target/benchmarks.jar ".*FileAppenderBenchmark.*" -f 1 -i 5 -wi 5 -bm sample -tu ns
 @State(Scope.Thread)
 public class FileAppenderBenchmark {
+    public static final String MESSAGE = "This is a debug message";
+    private FileHandler julFileHandler;
+
     Logger log4j2Logger;
     Logger log4j2RandomLogger;
     org.slf4j.Logger slf4jLogger;
     org.apache.log4j.Logger log4j1Logger;
-    int j;
+    java.util.logging.Logger julLogger;
 
     @Setup
-    public void setUp() {
+    public void setUp() throws Exception {
         System.setProperty("log4j.configurationFile", "log4j2-perf.xml");
         System.setProperty("log4j.configuration", "log4j12-perf.xml");
         System.setProperty("logback.configurationFile", "logback-perf.xml");
 
-        File logbackFile = new File("target/testlogback.log");
-        logbackFile.delete();
-        File log4jFile = new File ("target/testlog4j.log");
-        log4jFile.delete();
-        File log4j2File = new File ("target/testlog4j2.log");
-        log4j2File.delete();
-        File log4j2RAF = new File ("target/testRandomlog4j2.log");
-        log4j2RAF.delete();
+        deleteLogFiles();
 
         log4j2Logger = LogManager.getLogger(FileAppenderBenchmark.class);
         log4j2RandomLogger = LogManager.getLogger("TestRandom");
         slf4jLogger = LoggerFactory.getLogger(FileAppenderBenchmark.class);
         log4j1Logger = org.apache.log4j.Logger.getLogger(FileAppenderBenchmark.class);
-        j = 0;
+
+        julFileHandler = new FileHandler("target/testJulLog.log");
+        julLogger = java.util.logging.Logger.getLogger(getClass().getName());
+        julLogger.setUseParentHandlers(false);
+        julLogger.addHandler(julFileHandler);
+        julLogger.setLevel(Level.ALL);
     }
 
     @TearDown
@@ -74,6 +77,10 @@ public class FileAppenderBenchmark {
         System.clearProperty("log4j.configuration");
         System.clearProperty("logback.configurationFile");
 
+        deleteLogFiles();
+    }
+
+    private void deleteLogFiles() {
         File logbackFile = new File("target/testlogback.log");
         logbackFile.delete();
         File log4jFile = new File ("target/testlog4j.log");
@@ -82,63 +89,44 @@ public class FileAppenderBenchmark {
         log4jRandomFile.delete();
         File log4j2File = new File ("target/testlog4j2.log");
         log4j2File.delete();
+        File julFile = new File("target/testJulLog.log");
+        julFile.delete();
     }
 
     @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
-    @Benchmark
-    public boolean baseline() {
-        ++j;
-        return true;
-    }
-
-    @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
-    @Benchmark
-    public void log4j2RAFStringConcatenation() {
-        log4j2RandomLogger.debug("This is a debug [" + ++j + "] message");
-    }
-
-
-    @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
+    @OutputTimeUnit(TimeUnit.SECONDS)
     @Benchmark
-    public void log4j2StringConcatenation() {
-        log4j2Logger.debug("This is a debug [" + ++j + "] message");
+    public void log4j2RAF() {
+        log4j2RandomLogger.debug(MESSAGE);
     }
 
-    @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
-    @Benchmark
-    public void slf4jStringConcatenation() {
-        slf4jLogger.debug("This is a debug [" + ++j + "] message");
-    }
 
     @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
+    @OutputTimeUnit(TimeUnit.SECONDS)
     @Benchmark
-    public void log4j1StringConcatenation() {
-        log4j1Logger.debug("This is a debug [" + ++j + "] message");
+    public void log4j2File() {
+        log4j2Logger.debug(MESSAGE);
     }
 
     @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
+    @OutputTimeUnit(TimeUnit.SECONDS)
     @Benchmark
-    public void log4j2RAFParameterizedString() {
-        log4j2RandomLogger.debug("This is a debug [{}] message", ++j);
+    public void logbackFile() {
+        slf4jLogger.debug(MESSAGE);
     }
 
     @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
+    @OutputTimeUnit(TimeUnit.SECONDS)
     @Benchmark
-    public void log4j2ParameterizedString() {
-        log4j2Logger.debug("This is a debug [{}] message", ++j);
+    public void log4j1File() {
+        log4j1Logger.debug(MESSAGE);
     }
 
     @BenchmarkMode(Mode.Throughput)
-    @OutputTimeUnit(TimeUnit.MILLISECONDS)
+    @OutputTimeUnit(TimeUnit.SECONDS)
     @Benchmark
-    public void slf4jParameterizedString() {
-        slf4jLogger.debug("This is a debug [{}] message", ++j);
+    public void julFile() {
+        // must specify sourceClass or JUL will look it up by walking the stack trace!
+        julLogger.logp(Level.INFO, getClass().getName(), "julFile", MESSAGE);
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f226b972/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderParamsBenchmark.java
----------------------------------------------------------------------
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderParamsBenchmark.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderParamsBenchmark.java
new file mode 100644
index 0000000..6865381
--- /dev/null
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/jmh/FileAppenderParamsBenchmark.java
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+package org.apache.logging.log4j.perf.jmh;
+
+import java.io.File;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.logging.log4j.util.Unbox.*;
+
+/**
+ * Benchmarks Log4j 2, Log4j 1, Logback and JUL using the DEBUG level which is enabled for this test. The configuration
+ * for each uses a FileAppender
+ */
+// HOW TO RUN THIS TEST
+// java -jar target/benchmarks.jar ".*FileAppenderParamsBenchmark.*" -f 1 -i 5 -wi 5 -bm sample -tu ns
+@State(Scope.Thread)
+public class FileAppenderParamsBenchmark {
+    private FileHandler julFileHandler;
+    Logger log4j2Logger;
+    Logger log4j2RandomLogger;
+    org.slf4j.Logger slf4jLogger;
+    org.apache.log4j.Logger log4j1Logger;
+    java.util.logging.Logger julLogger;
+    int j, k, m;
+
+    @Setup
+    public void setUp() throws Exception {
+        System.setProperty("log4j.configurationFile", "log4j2-perf.xml");
+        System.setProperty("log4j.configuration", "log4j12-perf.xml");
+        System.setProperty("logback.configurationFile", "logback-perf.xml");
+
+        deleteLogFiles();
+
+        log4j2Logger = LogManager.getLogger(getClass());
+        log4j2RandomLogger = LogManager.getLogger("TestRandom");
+        slf4jLogger = LoggerFactory.getLogger(getClass());
+        log4j1Logger = org.apache.log4j.Logger.getLogger(getClass());
+
+        julFileHandler = new FileHandler("target/testJulLog.log");
+        julLogger = java.util.logging.Logger.getLogger(getClass().getName());
+        julLogger.setUseParentHandlers(false);
+        julLogger.addHandler(julFileHandler);
+        julLogger.setLevel(Level.ALL);
+        j = 0;
+    }
+
+    @TearDown
+    public void tearDown() {
+        System.clearProperty("log4j.configurationFile");
+        System.clearProperty("log4j.configuration");
+        System.clearProperty("logback.configurationFile");
+
+        deleteLogFiles();
+    }
+
+    private void deleteLogFiles() {
+        File logbackFile = new File("target/testlogback.log");
+        logbackFile.delete();
+        File log4jFile = new File ("target/testlog4j.log");
+        log4jFile.delete();
+        File log4jRandomFile = new File ("target/testRandomlog4j2.log");
+        log4jRandomFile.delete();
+        File log4j2File = new File ("target/testlog4j2.log");
+        log4j2File.delete();
+        File julFile = new File("target/testJulLog.log");
+        julFile.delete();
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param1Log4j1Concat() {
+        log4j1Logger.debug("This is a debug [" + ++j + "] message");
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param3Log4j1Concat() {
+        log4j1Logger.debug("Val1=" + ++j + ", val2=" + ++k + ", val3=" + ++m);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param1Log4j2RAF() {
+        log4j2RandomLogger.debug("This is a debug [{}] message", box(++j));
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param3Log4j2RAF() {
+        log4j2RandomLogger.debug("Val1={}, val2={}, val3={}", box(++j), box(++k), box(++m));
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param1Log4j2File() {
+        log4j2Logger.debug("This is a debug [{}] message", box(++j));
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param3Log4j2File() {
+        log4j2Logger.debug("Val1={}, val2={}, val3={}", box(++j), box(++k), box(++m));
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param1LogbackFile() {
+        slf4jLogger.debug("This is a debug [{}] message", ++j);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param3LogbackFile() {
+        slf4jLogger.debug("Val1={}, val2={}, val3={}", (++j), (++k), (++m));
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param1JulFile() {
+        // must specify sourceClass or JUL will look it up by walking the stack trace!
+        julLogger.logp(Level.INFO, getClass().getName(), "param1JulFile", "This is a debug [{}] message", ++j);
+    }
+
+    @BenchmarkMode(Mode.Throughput)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @Benchmark
+    public void param3JulFile() {
+        // must specify sourceClass or JUL will look it up by walking the stack trace!
+        julLogger.logp(Level.INFO, getClass().getName(), "param3JulFile", "Val1={}, val2={}, val3={}",
+                new Object[]{++j, ++k, ++m});
+    }
+}


[18/38] logging-log4j2 git commit: LOG4J2-1342 use new method ReusableMessage#memento() to take snapshot without losing parameter information

Posted by rg...@apache.org.
LOG4J2-1342 use new method ReusableMessage#memento() to take snapshot without losing parameter information


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/04ee75ff
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/04ee75ff
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/04ee75ff

Branch: refs/heads/master
Commit: 04ee75ff52276f02caa248a33bc8c0da7ded10ef
Parents: c172995
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:39:34 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/04ee75ff/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
index 26b35d3..776fba7 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
@@ -844,7 +844,7 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
         }
 
         private Message memento(final ReusableMessage message) {
-            return new SimpleMessage(message.getFormattedMessage());
+            return message.memento();
         }
 
         /**


[10/38] logging-log4j2 git commit: LOG4J2-1342 ensure internal array is not set to null by incorrect swap() invocation

Posted by rg...@apache.org.
LOG4J2-1342 ensure internal array is not set to null by incorrect swap() invocation


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/047202aa
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/047202aa
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/047202aa

Branch: refs/heads/master
Commit: 047202aa1fc3681f1f546eebd08f2a94b426a993
Parents: fb5e730
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 12:51:13 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/message/ReusableParameterizedMessage.java     | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/047202aa/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index 4913c64..12f4346 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.message;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 import org.apache.logging.log4j.util.PerformanceSensitive;
 
@@ -61,10 +62,10 @@ public class ReusableParameterizedMessage implements ReusableMessage {
         Object[] result;
         if (varargs == null) {
             result = params;
-            params = emptyReplacement;
+            params = Objects.requireNonNull(emptyReplacement);
         } else {
             result = varargs;
-            varargs = emptyReplacement;
+            varargs = Objects.requireNonNull(emptyReplacement);
         }
         return result;
     }


[20/38] logging-log4j2 git commit: LOG4J2-1334 don't take snapshot of message, delegate to MutableLogEvent

Posted by rg...@apache.org.
LOG4J2-1334 don't take snapshot of message, delegate to MutableLogEvent


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e7fea765
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e7fea765
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e7fea765

Branch: refs/heads/master
Commit: e7fea76570a1d30dd91cb9e54bfda13396d99f5e
Parents: b2e90dc
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:33:28 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/async/AsyncLoggerConfigDisruptor.java     | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e7fea765/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
index 503e7d8..60494e0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
@@ -145,7 +145,7 @@ public class AsyncLoggerConfigDisruptor implements AsyncLoggerConfigDelegate {
     private static final EventFactory<Log4jEventWrapper> MUTABLE_FACTORY = new EventFactory<Log4jEventWrapper>() {
         @Override
         public Log4jEventWrapper newInstance() {
-            return new Log4jEventWrapper(new MutableLogEvent(new Object[10]));
+            return new Log4jEventWrapper(new MutableLogEvent());
         }
     };
 
@@ -324,8 +324,6 @@ public class AsyncLoggerConfigDisruptor implements AsyncLoggerConfigDelegate {
         final LogEvent logEvent = ensureImmutable(event);
         if (logEvent instanceof Log4jLogEvent && logEvent.getMessage() instanceof ReusableMessage) {
             ((Log4jLogEvent) logEvent).makeMessageImmutable();
-        } else if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND) { // LOG4J2-898: user may choose
-            logEvent.getMessage().getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters
         }
         return logEvent;
     }


[17/38] logging-log4j2 git commit: LOG4J2-1334 synchronous logging is now garbage-free; enable this by default

Posted by rg...@apache.org.
LOG4J2-1334	synchronous logging is now garbage-free; enable this by default


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/22e98d60
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/22e98d60
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/22e98d60

Branch: refs/heads/master
Commit: 22e98d608d11b950bc90c582d996fbe94822329b
Parents: 04ee75f
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:54:09 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../java/org/apache/logging/log4j/core/config/LoggerConfig.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/22e98d60/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
index 7b030c6..3a3e04c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/LoggerConfig.java
@@ -84,7 +84,7 @@ public class LoggerConfig extends AbstractFilterable {
             }
         }
         if (LOG_EVENT_FACTORY == null) {
-            LOG_EVENT_FACTORY = false //Constants.ENABLE_THREADLOCALS
+            LOG_EVENT_FACTORY = Constants.ENABLE_THREADLOCALS
                     ? new ReusableLogEventFactory()
                     : new DefaultLogEventFactory();
         }


[15/38] logging-log4j2 git commit: LOG4J2-1342 added methods to ReusableMessage to enable passing parameters to async logger background threads

Posted by rg...@apache.org.
LOG4J2-1342 added methods to ReusableMessage to enable passing parameters to async logger background threads


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/79e51b23
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/79e51b23
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/79e51b23

Branch: refs/heads/master
Commit: 79e51b23e1b74b9233c603067fd1da2f0a721130
Parents: 873e19b
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 12:10:34 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/message/ReusableMessage.java  | 31 +++++++
 .../log4j/message/ReusableObjectMessage.java    | 19 ++++
 .../message/ReusableParameterizedMessage.java   | 20 ++++
 .../log4j/message/ReusableSimpleMessage.java    | 18 ++++
 .../core/async/AsyncLoggerConfigDisruptor.java  |  2 +-
 .../log4j/core/async/RingBufferLogEvent.java    | 98 +++++++++++++-------
 .../log4j/core/impl/MutableLogEvent.java        | 67 ++++++++++---
 7 files changed, 209 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
index a6da9c4..0536b23 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
@@ -30,4 +30,35 @@ import org.apache.logging.log4j.util.StringBuilderFormattable;
  */
 @PerformanceSensitive("allocation")
 public interface ReusableMessage extends Message, StringBuilderFormattable {
+
+    /**
+     * Returns the parameter array that was used to initialize this reusable message and replaces it with the specified
+     * array. The returned parameter array will no longer be modified by this reusable message. The specified array is
+     * now "owned" by this reusable message and can be modified if necessary for the next log event.
+     * </p><p>
+     * ReusableMessages that have no parameters return the specified array.
+     * </p><p>
+     * This method is used by asynchronous loggers to pass the parameter array to a background thread without
+     * allocating new objects.
+     * The actual number of parameters in the returned array can be determined with {@link #getParameterCount()}.
+     * </p>
+     *
+     * @param emptyReplacement the parameter array that can be used for subsequent uses of this reusable message.
+     *         This replacement array must have at least 10 elements (the number of varargs supported by the Logger
+     *         API).
+     * @return the parameter array for the current message content. This may be a vararg array of any length, or it may
+     *         be a reusable array of 10 elements used to hold the unrolled vararg parameters.
+     * @see #getParameterCount()
+     */
+    Object[] swapParameters(Object[] emptyReplacement);
+
+    /**
+     * Returns the number of parameters that was used to initialize this reusable message for the current content.
+     * <p>
+     * The parameter array returned by {@link #swapParameters(Object[])} may be larger than the actual number of
+     * parameters. Callers should use this method to determine how many elements the array contains.
+     * </p>
+     * @return the current number of parameters
+     */
+    short getParameterCount();
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
index 12f62f4..920eff4 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableObjectMessage.java
@@ -91,4 +91,23 @@ public class ReusableObjectMessage implements ReusableMessage {
     public Throwable getThrowable() {
         return obj instanceof Throwable ? (Throwable) obj : null;
     }
+
+    /**
+     * This message does not have any parameters, so this method returns the specified array.
+     * @param emptyReplacement the parameter array to return
+     * @return the specified array
+     */
+    @Override
+    public Object[] swapParameters(final Object[] emptyReplacement) {
+        return emptyReplacement;
+    }
+
+    /**
+     * This message does not have any parameters so this method always returns zero.
+     * @return 0 (zero)
+     */
+    @Override
+    public short getParameterCount() {
+        return 0;
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index 87cdc1d..4913c64 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -55,6 +55,26 @@ public class ReusableParameterizedMessage implements ReusableMessage {
         return varargs == null ? params : varargs;
     }
 
+    // see interface javadoc
+    @Override
+    public Object[] swapParameters(final Object[] emptyReplacement) {
+        Object[] result;
+        if (varargs == null) {
+            result = params;
+            params = emptyReplacement;
+        } else {
+            result = varargs;
+            varargs = emptyReplacement;
+        }
+        return result;
+    }
+
+    // see interface javadoc
+    @Override
+    public short getParameterCount() {
+        return (short) argCount;
+    }
+
     private void init(final String messagePattern, final int argCount, final Object[] paramArray) {
         this.varargs = null;
         this.messagePattern = messagePattern;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
index ed6e39e..9fae16c 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableSimpleMessage.java
@@ -61,6 +61,24 @@ public class ReusableSimpleMessage implements ReusableMessage, CharSequence {
         buffer.append(charSequence);
     }
 
+    /**
+     * This message does not have any parameters, so this method returns the specified array.
+     * @param emptyReplacement the parameter array to return
+     * @return the specified array
+     */
+    @Override
+    public Object[] swapParameters(final Object[] emptyReplacement) {
+        return emptyReplacement;
+    }
+
+    /**
+     * This message does not have any parameters so this method always returns zero.
+     * @return 0 (zero)
+     */
+    @Override
+    public short getParameterCount() {
+        return 0;
+    }
 
     // CharSequence impl
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
index 2c1b84f..503e7d8 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
@@ -145,7 +145,7 @@ public class AsyncLoggerConfigDisruptor implements AsyncLoggerConfigDelegate {
     private static final EventFactory<Log4jEventWrapper> MUTABLE_FACTORY = new EventFactory<Log4jEventWrapper>() {
         @Override
         public Log4jEventWrapper newInstance() {
-            return new Log4jEventWrapper(new MutableLogEvent());
+            return new Log4jEventWrapper(new MutableLogEvent(new Object[10]));
         }
     };
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index e1e6ab0..72ae8ac 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -16,7 +16,11 @@
  */
 package org.apache.logging.log4j.core.async;
 
-import com.lmax.disruptor.EventFactory;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.ThreadContext.ContextStack;
@@ -32,9 +36,7 @@ import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.message.TimestampMessage;
 import org.apache.logging.log4j.util.Strings;
 
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
+import com.lmax.disruptor.EventFactory;
 
 /**
  * When the Disruptor is started, the RingBuffer is populated with event objects. These objects are then re-used during
@@ -46,7 +48,6 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
     public static final Factory FACTORY = new Factory();
 
     private static final long serialVersionUID = 8462119088943934758L;
-    private static final Object[] PARAMS = new Object[0];
     private static final Message EMPTY = new SimpleMessage(Strings.EMPTY);
 
     /**
@@ -59,56 +60,63 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
             RingBufferLogEvent result = new RingBufferLogEvent();
             if (Constants.ENABLE_THREADLOCALS) {
                 result.messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE);
+                result.parameters = new Object[10];
             }
             return result;
         }
     }
 
-    private transient AsyncLogger asyncLogger;
-    private String loggerName;
-    private Marker marker;
-    private String fqcn;
+    private int threadPriority;
+    private long threadId;
+    private long currentTimeMillis;
+    private long nanoTime;
+    private short parameterCount;
+    private boolean includeLocation;
+    private boolean endOfBatch = false;
     private Level level;
-    private StringBuilder messageText;
+    private String threadName;
+    private String loggerName;
     private Message message;
+    private StringBuilder messageText;
+    private Object[] parameters;
     private transient Throwable thrown;
     private ThrowableProxy thrownProxy;
     private Map<String, String> contextMap;
-    private ContextStack contextStack;
-    private long threadId;
-    private String threadName;
-    private int threadPriority;
+    private Marker marker;
+    private String fqcn;
     private StackTraceElement location;
-    private long currentTimeMillis;
-    private boolean endOfBatch;
-    private boolean includeLocation;
-    private long nanoTime;
+    private ContextStack contextStack;
+
+    private transient AsyncLogger asyncLogger;
 
     public void setValues(final AsyncLogger anAsyncLogger, final String aLoggerName, final Marker aMarker,
             final String theFqcn, final Level aLevel, final Message msg, final Throwable aThrowable,
             final Map<String, String> aMap, final ContextStack aContextStack, long threadId,
             final String threadName, int threadPriority, final StackTraceElement aLocation, final long aCurrentTimeMillis, final long aNanoTime) {
-        this.asyncLogger = anAsyncLogger;
-        this.loggerName = aLoggerName;
-        this.marker = aMarker;
-        this.fqcn = theFqcn;
+        this.threadPriority = threadPriority;
+        this.threadId = threadId;
+        this.currentTimeMillis = aCurrentTimeMillis;
+        this.nanoTime = aNanoTime;
         this.level = aLevel;
+        this.threadName = threadName;
+        this.loggerName = aLoggerName;
+        setMessage(msg);
         this.thrown = aThrowable;
         this.thrownProxy = null;
         this.contextMap = aMap;
-        this.contextStack = aContextStack;
-        this.threadId = threadId;
-        this.threadName = threadName;
-        this.threadPriority = threadPriority;
+        this.marker = aMarker;
+        this.fqcn = theFqcn;
         this.location = aLocation;
-        this.currentTimeMillis = aCurrentTimeMillis;
-        this.nanoTime = aNanoTime;
-        setMessage(msg);
+        this.contextStack = aContextStack;
+        this.asyncLogger = anAsyncLogger;
     }
 
     private void setMessage(final Message msg) {
         if (msg instanceof ReusableMessage) {
-            ((ReusableMessage) msg).formatTo(getMessageTextForWriting());
+            ReusableMessage reusable = (ReusableMessage) msg;
+            reusable.formatTo(getMessageTextForWriting());
+            parameters = reusable.swapParameters(parameters);
+            parameterCount = reusable.getParameterCount();
         } else {
             // if the Message instance is reused, there is no point in freezing its message here
             if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND && msg != null) { // LOG4J2-898: user may choose
@@ -215,7 +223,7 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
      */
     @Override
     public Object[] getParameters() {
-        return PARAMS;
+        return parameters == null ? null : Arrays.copyOf(parameters, parameterCount);
     }
 
     /**
@@ -234,6 +242,27 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
         buffer.append(messageText);
     }
 
+    /**
+     * Replaces this ReusableMessage's parameter array with the specified value and return the original array
+     * @param emptyReplacement the parameter array that can be used for subsequent uses of this reusable message
+     * @return the original parameter array
+     * @see ReusableMessage#swapParameters(Object[])
+     */
+    @Override
+    public Object[] swapParameters(final Object[] emptyReplacement) {
+        final Object[] result = this.parameters;
+        this.parameters = emptyReplacement;
+        return result;
+    }
+
+    /*
+     * @see ReusableMessage#getParameterCount
+     */
+    @Override
+    public short getParameterCount() {
+        return parameterCount;
+    }
+
 
     // CharSequence impl
 
@@ -362,7 +391,14 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
         this.contextMap = null;
         this.contextStack = null;
         this.location = null;
+
         trimMessageText();
+
+        if (parameters != null) {
+            for (int i = 0; i < parameters.length; i++) {
+                parameters[i] = null;
+            }
+        }
     }
 
     // ensure that excessively long char[] arrays are not kept in memory forever

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/79e51b23/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
index b619615..0393b0c 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.impl;
 
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
+import java.util.Arrays;
 import java.util.Map;
 
 import org.apache.logging.log4j.Level;
@@ -35,27 +36,36 @@ import org.apache.logging.log4j.util.Strings;
  * @since 2.6
  */
 public class MutableLogEvent implements LogEvent, ReusableMessage {
-    private static final Object[] PARAMS = new Object[0];
     private static final Message EMPTY = new SimpleMessage(Strings.EMPTY);
 
-    private String loggerFqcn;
-    private Marker marker;
+    private int threadPriority;
+    private long threadId;
+    private long timeMillis;
+    private long nanoTime;
+    private short parameterCount;
+    private boolean includeLocation;
+    private boolean endOfBatch = false;
     private Level level;
+    private String threadName;
     private String loggerName;
     private Message message;
-    private long timeMillis;
+    private StringBuilder messageText;
+    private Object[] parameters;
     private Throwable thrown;
     private ThrowableProxy thrownProxy;
     private Map<String, String> contextMap;
-    private ThreadContext.ContextStack contextStack;
-    private long threadId;
-    private String threadName;
-    private int threadPriority;
+    private Marker marker;
+    private String loggerFqcn;
     private StackTraceElement source;
-    private boolean includeLocation;
-    private boolean endOfBatch = false;
-    private long nanoTime;
-    private StringBuilder messageText;
+    private ThreadContext.ContextStack contextStack;
+
+    public MutableLogEvent() {
+        this(null);
+    }
+
+    public MutableLogEvent(final Object[] replacementParameters) {
+        this.parameters = replacementParameters;
+    }
 
     /**
      * Initialize the fields of this {@code MutableLogEvent} from another event.
@@ -107,6 +117,11 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
         // threadName = null; // no need to clear threadName
 
         trimMessageText();
+        if (parameters != null) {
+            for (int i = 0; i < parameters.length; i++) {
+                parameters[i] = null;
+            }
+        }
 
         // primitive fields that cannot be cleared:
         //timeMillis;
@@ -171,7 +186,10 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
 
     public void setMessage(final Message msg) {
         if (msg instanceof ReusableMessage) {
-            ((ReusableMessage) msg).formatTo(getMessageTextForWriting()); // init messageText
+            ReusableMessage reusable = (ReusableMessage) msg;
+            reusable.formatTo(getMessageTextForWriting());
+            parameters = reusable.swapParameters(parameters);
+            parameterCount = reusable.getParameterCount();
         } else {
             // if the Message instance is reused, there is no point in freezing its message here
             if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND && msg != null) { // LOG4J2-898: user may choose
@@ -212,7 +230,7 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
      */
     @Override
     public Object[] getParameters() {
-        return PARAMS;
+        return parameters == null ? null : Arrays.copyOf(parameters, parameterCount);
     }
 
     /**
@@ -231,6 +249,27 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
         buffer.append(messageText);
     }
 
+    /**
+     * Replaces this ReusableMessage's parameter array with the specified value and return the original array
+     * @param emptyReplacement the parameter array that can be used for subsequent uses of this reusable message
+     * @return the original parameter array
+     * @see ReusableMessage#swapParameters(Object[])
+     */
+    @Override
+    public Object[] swapParameters(final Object[] emptyReplacement) {
+        final Object[] result = this.parameters;
+        this.parameters = emptyReplacement;
+        return result;
+    }
+
+    /*
+     * @see ReusableMessage#getParameterCount
+     */
+    @Override
+    public short getParameterCount() {
+        return parameterCount;
+    }
+
     @Override
     public Throwable getThrown() {
         return thrown;


[02/38] logging-log4j2 git commit: LOG4J2-494 - Support reconfiguration. Fix status logging issues

Posted by rg...@apache.org.
LOG4J2-494 - Support reconfiguration. Fix status logging issues


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/e975a89f
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/e975a89f
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/e975a89f

Branch: refs/heads/master
Commit: e975a89f75f3d0200d5033b7286daded67756d6d
Parents: bb64f45
Author: Ralph Goers <rg...@nextiva.com>
Authored: Mon Apr 25 06:31:13 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 06:31:13 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/status/StatusLogger.java      |   6 +
 .../log4j/core/config/ConfigurationFactory.java |   2 +-
 .../logging/log4j/core/config/Configurator.java |   2 +-
 .../builder/api/ConfigurationBuilder.java       |  17 ++
 .../impl/DefaultConfigurationBuilder.java       |  16 +-
 .../composite/CompositeConfiguration.java       |  63 +++---
 .../config/composite/DefaultMergeStrategy.java  |  38 ++--
 .../core/config/composite/MergeStrategy.java    |   8 +
 .../properties/PropertiesConfiguration.java     |   2 +-
 .../PropertiesConfigurationBuilder.java         |   9 +-
 .../core/config/status/StatusConfiguration.java |   1 +
 .../core/config/CompositeConfigurationTest.java | 191 +++++++++++--------
 .../log4j/core/config/TestConfigurator.java     |  11 +-
 .../src/test/resources/log4j-comp-appender.xml  |   2 +-
 .../src/test/resources/log4j-comp-filter.xml    |   2 +-
 .../test/resources/log4j-comp-properties.xml    |   2 +-
 .../resources/log4j-comp-reconfig.properties    |  59 ++++++
 .../src/test/resources/log4j-comp-reconfig.xml  |  39 ++++
 18 files changed, 339 insertions(+), 131 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
index ebd44d4..902b444 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/status/StatusLogger.java
@@ -141,6 +141,12 @@ public final class StatusLogger extends AbstractLogger {
         }
     }
 
+    public void updateListenerLevel(final Level status) {
+        if (status.intLevel() > listenersLevel) {
+            listenersLevel = status.intLevel();
+        }
+    }
+
     /**
      * Returns a thread safe Iterable for the StatusListener.
      *

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
index 41f3571..32cfe90 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/ConfigurationFactory.java
@@ -397,7 +397,7 @@ public abstract class ConfigurationFactory extends ConfigurationBuilderFactory {
                     if (sources.length > 1) {
                         List<AbstractConfiguration> configs = new ArrayList<>();
                         for (String sourceLocation : sources) {
-                            Configuration config = getConfiguration(sourceLocation);
+                            Configuration config = getConfiguration(sourceLocation.trim());
                             if (config != null && config instanceof AbstractConfiguration) {
                                 configs.add((AbstractConfiguration) config);
                             } else {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
index f0e462e..147c20f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/Configurator.java
@@ -119,7 +119,7 @@ public final class Configurator {
             String scheme = null;
             List<URI> uris = new ArrayList<>(parts.length);
             for (String part : parts) {
-                URI uri = NetUtils.toURI(scheme != null ? scheme + ":" + part : part);
+                URI uri = NetUtils.toURI(scheme != null ? scheme + ":" + part.trim() : part.trim());
                 if (scheme == null && uri.getScheme() != null) {
                     scheme = uri.getScheme();
                 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java
index 4b4473d..eab7044 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/api/ConfigurationBuilder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.config.builder.api;
 
+import java.util.Map;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Filter;
 import org.apache.logging.log4j.core.config.Configuration;
@@ -379,4 +380,20 @@ public interface ConfigurationBuilder<T extends Configuration> extends Builder<T
      * @return this builder instance.
      */
     ConfigurationBuilder<T> setVerbosity(String verbosity);
+
+    /**
+     * Add the properties for the root node.
+     * @param key The property key.
+     * @param value The property value.
+     * @return this builder instance.
+     */
+    ConfigurationBuilder<T> addRootProperty(String key, String value);
+
+    /**
+     * Build the configuration and optionally initialize it.
+     * @param initialize true if the configuration should be initialized, false otherwise. Generally, Configurations
+     *                   should not be initialized when they are constructed.
+     * @return The constructed Configuration.
+     */
+    T build(boolean initialize);
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
index 8e4364f..8043ff5 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/builder/impl/DefaultConfigurationBuilder.java
@@ -141,6 +141,11 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement
 
     @Override
     public T build() {
+        return build(true);
+    }
+
+    @Override
+    public T build(boolean initialize) {
         T configuration;
         try {
             if (source == null) {
@@ -149,6 +154,7 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement
             final Constructor<T> constructor = clazz.getConstructor(ConfigurationSource.class, Component.class);
             configuration = constructor.newInstance(source, root);
             configuration.setMonitorInterval(monitorInterval);
+            configuration.getRootNode().getAttributes().putAll(root.getAttributes());
             if (name != null) {
                 configuration.setName(name);
             }
@@ -171,7 +177,9 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement
             throw new IllegalArgumentException("Invalid Configuration class specified", ex);
         }
         configuration.getStatusConfiguration().initialize();
-        configuration.initialize();
+        if (initialize) {
+            configuration.initialize();
+        }
         return configuration;
     }
 
@@ -380,4 +388,10 @@ public class DefaultConfigurationBuilder<T extends BuiltConfiguration> implement
         this.verbosity = verbosity;
         return this;
     }
+
+    @Override
+    public ConfigurationBuilder<T> addRootProperty(String key, String value) {
+        root.getAttributes().put(key, value);
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
index 8b416b3..68fbc3b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/CompositeConfiguration.java
@@ -63,6 +63,7 @@ public class CompositeConfiguration extends AbstractConfiguration implements Rec
      */
     public CompositeConfiguration(List<? extends AbstractConfiguration> configurations) {
         super(ConfigurationSource.NULL_SOURCE);
+        rootNode = configurations.get(0).getRootNode();
         this.configurations = configurations;
         String mergeStrategyClassName = PropertiesUtil.getProperties().getStringProperty(MERGE_STRATEGY_PROPERTY,
                 DefaultMergeStrategy.class.getName());
@@ -72,14 +73,47 @@ public class CompositeConfiguration extends AbstractConfiguration implements Rec
                 InstantiationException ex) {
             mergeStrategy = new DefaultMergeStrategy();
         }
+        for (AbstractConfiguration config : configurations) {
+            mergeStrategy.mergeRootProperties(rootNode, config);
+        }
+        final StatusConfiguration statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES)
+                .withStatus(getDefaultStatus());
+        for (final Map.Entry<String, String> entry : rootNode.getAttributes().entrySet()) {
+            final String key = entry.getKey();
+            final String value = getStrSubstitutor().replace(entry.getValue());
+            if ("status".equalsIgnoreCase(key)) {
+                statusConfig.withStatus(value.toUpperCase());
+            } else if ("dest".equalsIgnoreCase(key)) {
+                statusConfig.withDestination(value);
+            } else if ("shutdownHook".equalsIgnoreCase(key)) {
+                isShutdownHookEnabled = !"disable".equalsIgnoreCase(value);
+            } else if ("verbose".equalsIgnoreCase(key)) {
+                statusConfig.withVerbosity(value);
+            } else if ("packages".equalsIgnoreCase(key)) {
+                pluginPackages.addAll(Arrays.asList(value.split(Patterns.COMMA_SEPARATOR)));
+            } else if ("name".equalsIgnoreCase(key)) {
+                setName(value);
+            }
+        }
+        statusConfig.initialize();
     }
 
     @Override
     public void setup() {
         AbstractConfiguration targetConfiguration = configurations.get(0);
         staffChildConfiguration(targetConfiguration);
-        WatchManager watchManager = targetConfiguration.getWatchManager();
-        rootNode = targetConfiguration.getRootNode();
+        WatchManager watchManager = getWatchManager();
+        WatchManager targetWatchManager = targetConfiguration.getWatchManager();
+        FileWatcher fileWatcher = new ConfiguratonFileWatcher(this, listeners);
+        if (targetWatchManager.getIntervalSeconds() > 0) {
+            watchManager.setIntervalSeconds(targetWatchManager.getIntervalSeconds());
+            Map<File, FileWatcher> watchers = targetWatchManager.getWatchers();
+            for (Map.Entry<File, FileWatcher> entry : watchers.entrySet()) {
+                if (entry.getValue() instanceof ConfiguratonFileWatcher) {
+                    watchManager.watchFile(entry.getKey(), fileWatcher);
+                }
+            }
+        }
         for (AbstractConfiguration sourceConfiguration : configurations.subList(1, configurations.size())) {
             staffChildConfiguration(sourceConfiguration);
             Node sourceRoot = sourceConfiguration.getRootNode();
@@ -91,12 +125,12 @@ public class CompositeConfiguration extends AbstractConfiguration implements Rec
             }
             int monitorInterval = sourceConfiguration.getWatchManager().getIntervalSeconds();
             if (monitorInterval > 0) {
-                if (monitorInterval < watchManager.getIntervalSeconds()) {
+                int currentInterval = watchManager.getIntervalSeconds();
+                if (currentInterval <= 0 || monitorInterval < currentInterval) {
                     watchManager.setIntervalSeconds(monitorInterval);
                 }
                 WatchManager sourceWatchManager = sourceConfiguration.getWatchManager();
                 Map<File, FileWatcher> watchers = sourceWatchManager.getWatchers();
-                FileWatcher fileWatcher = new ConfiguratonFileWatcher(this, listeners);
                 for (Map.Entry<File, FileWatcher> entry : watchers.entrySet()) {
                     if (entry.getValue() instanceof ConfiguratonFileWatcher) {
                         watchManager.watchFile(entry.getKey(), fileWatcher);
@@ -104,30 +138,11 @@ public class CompositeConfiguration extends AbstractConfiguration implements Rec
                 }
             }
         }
-        final StatusConfiguration statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES)
-                .withStatus(getDefaultStatus());
-        for (final Map.Entry<String, String> entry : rootNode.getAttributes().entrySet()) {
-            final String key = entry.getKey();
-            final String value = getStrSubstitutor().replace(entry.getValue());
-            if ("status".equalsIgnoreCase(key)) {
-                statusConfig.withStatus(value);
-            } else if ("dest".equalsIgnoreCase(key)) {
-                statusConfig.withDestination(value);
-            } else if ("shutdownHook".equalsIgnoreCase(key)) {
-                isShutdownHookEnabled = !"disable".equalsIgnoreCase(value);
-            } else if ("verbose".equalsIgnoreCase(key)) {
-                statusConfig.withVerbosity(value);
-            } else if ("packages".equalsIgnoreCase(key)) {
-                pluginPackages.addAll(Arrays.asList(value.split(Patterns.COMMA_SEPARATOR)));
-            } else if ("name".equalsIgnoreCase(key)) {
-                setName(value);
-            }
-        }
-        statusConfig.initialize();
     }
 
     @Override
     public Configuration reconfigure() {
+        LOGGER.debug("Reconfiguring composite configuration");
         List<AbstractConfiguration> configs = new ArrayList<>();
         ConfigurationFactory factory = ConfigurationFactory.getInstance();
         for (AbstractConfiguration config : configurations) {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
index 7b123a0..bcd719f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/DefaultMergeStrategy.java
@@ -22,6 +22,7 @@ import java.util.Map;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
 import org.apache.logging.log4j.core.config.Node;
 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
 import org.apache.logging.log4j.core.config.plugins.util.PluginType;
@@ -62,25 +63,27 @@ public class DefaultMergeStrategy implements MergeStrategy {
     private static final String REF = "ref";
 
     /**
-     * Merge the source Configuration into the target Configuration.
-     *
-     * @param target        The target node to merge into.
-     * @param source        The source node.
-     * @param pluginManager The PluginManager.
+     * Merge the root properties.
+     * @param rootNode The composite root node.
+     * @param configuration The configuration to merge.
      */
-    public void mergConfigurations(Node target, Node source, PluginManager pluginManager) {
-        for (Map.Entry<String, String> attribute : source.getAttributes().entrySet()) {
+    @Override
+    public void mergeRootProperties(Node rootNode, AbstractConfiguration configuration) {
+        for (Map.Entry<String, String> attribute : configuration.getRootNode().getAttributes().entrySet()) {
             boolean isFound = false;
-            for (Map.Entry<String, String> targetAttribute : target.getAttributes().entrySet()) {
+            for (Map.Entry<String, String> targetAttribute : rootNode.getAttributes().entrySet()) {
                 if (targetAttribute.getKey().equalsIgnoreCase(attribute.getKey())) {
                     if (attribute.getKey().equalsIgnoreCase(STATUS)) {
-                        Level targetLevel = Level.getLevel(targetAttribute.getValue());
-                        Level sourceLevel = Level.getLevel(attribute.getValue());
+                        Level targetLevel = Level.getLevel(targetAttribute.getValue().toUpperCase());
+                        Level sourceLevel = Level.getLevel(attribute.getValue().toUpperCase());
                         if (targetLevel != null && sourceLevel != null) {
                             if (sourceLevel.isLessSpecificThan(targetLevel)) {
                                 targetAttribute.setValue(attribute.getValue());
                             }
-                        }
+                        } else
+                            if (sourceLevel != null) {
+                                targetAttribute.setValue(attribute.getValue());
+                            }
                     } else {
                         if (attribute.getKey().equalsIgnoreCase("monitorInterval")) {
                             int sourceInterval = Integer.parseInt(attribute.getValue());
@@ -96,9 +99,20 @@ public class DefaultMergeStrategy implements MergeStrategy {
                 }
             }
             if (!isFound) {
-                target.getAttributes().put(attribute.getKey(), attribute.getValue());
+                rootNode.getAttributes().put(attribute.getKey(), attribute.getValue());
             }
         }
+    }
+
+    /**
+     * Merge the source Configuration into the target Configuration.
+     *
+     * @param target        The target node to merge into.
+     * @param source        The source node.
+     * @param pluginManager The PluginManager.
+     */
+    @Override
+    public void mergConfigurations(Node target, Node source, PluginManager pluginManager) {
         for (Node sourceChildNode : source.getChildren()) {
             boolean isFilter = isFilterNode(sourceChildNode);
             boolean isMerged = false;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
index 130a6f0..a01f6a3 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/composite/MergeStrategy.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.config.composite;
 
+import org.apache.logging.log4j.core.config.AbstractConfiguration;
 import org.apache.logging.log4j.core.config.Node;
 import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
 
@@ -25,6 +26,13 @@ import org.apache.logging.log4j.core.config.plugins.util.PluginManager;
 public interface MergeStrategy {
 
     /**
+     * Merge the root node properties into the configuration.
+     * @param rootNode The composite root node.
+     * @param configuration The configuration to merge.
+     */
+    void mergeRootProperties(Node rootNode, AbstractConfiguration configuration);
+
+    /**
      * Merge the soure node tree into the target node tree.
      * @param target The target Node tree.
      * @param source The source Node tree.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
index aa9eb59..90abf56 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfiguration.java
@@ -43,7 +43,7 @@ public class PropertiesConfiguration extends BuiltConfiguration implements Recon
             }
             final PropertiesConfigurationFactory factory = new PropertiesConfigurationFactory();
             final PropertiesConfiguration config = factory.getConfiguration(source);
-            return config == null || config.getState() != State.INITIALIZED ? null : config;
+            return config == null || config.getState() != State.INITIALIZING ? null : config;
         } catch (final IOException ex) {
             LOGGER.error("Cannot locate file {}: {}", getConfigurationSource(), ex);
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java
index 14a061f..51bdcca 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/properties/PropertiesConfigurationBuilder.java
@@ -17,6 +17,7 @@
 
 package org.apache.logging.log4j.core.config.properties;
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
@@ -77,6 +78,12 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory
 
     @Override
     public PropertiesConfiguration build() {
+        Map<String, String> rootProps = new HashMap<>();
+        for (String key : rootProperties.stringPropertyNames()) {
+            if (!key.contains(".")) {
+                builder.addRootProperty(key, rootProperties.getProperty(key));
+            }
+        }
         builder
             .setStatusLevel(Level.toLevel(rootProperties.getProperty(STATUS_KEY), Level.ERROR))
             .setShutdownHook(rootProperties.getProperty(SHUTDOWN_HOOK))
@@ -139,7 +146,7 @@ public class PropertiesConfigurationBuilder extends ConfigurationBuilderFactory
             builder.add(createRootLogger(props));
         }
 
-        return builder.build();
+        return builder.build(false);
     }
 
     private ScriptComponentBuilder createScript(final Properties properties) {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java
index ae15583..a6f4d1f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/config/status/StatusConfiguration.java
@@ -197,6 +197,7 @@ public class StatusConfiguration {
             if (statusListener instanceof StatusConsoleListener) {
                 final StatusConsoleListener listener = (StatusConsoleListener) statusListener;
                 listener.setLevel(this.status);
+                this.logger.updateListenerLevel(this.status);
                 if (this.verbosity == Verbosity.QUIET) {
                     listener.setFilters(this.verboseClasses);
                 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
index f17c941..be38342 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/CompositeConfigurationTest.java
@@ -1,10 +1,29 @@
+/*
+ * 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.
+ */
 package org.apache.logging.log4j.core.config;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
 
+import java.io.File;
 import java.util.Map;
 
+import java.util.concurrent.TimeUnit;
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.appender.ConsoleAppender;
 import org.apache.logging.log4j.core.appender.FileAppender;
@@ -17,133 +36,141 @@ import org.junit.Test;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-public class CompositeConfigurationTest
-{
+public class CompositeConfigurationTest {
 
     @Test
-    public void compositeConfigurationUsed()
-    {
-        final LoggerContextRule lcr =
-            new LoggerContextRule( "classpath:log4j-comp-appender.xml,log4j-comp-appender.json" );
-        Statement test = new Statement()
-        {
+    public void compositeConfigurationUsed() {
+        final LoggerContextRule lcr = new LoggerContextRule(
+                "classpath:log4j-comp-appender.xml,log4j-comp-appender.json");
+        Statement test = new Statement() {
             @Override
-            public void evaluate()
-                throws Throwable
-            {
-                assertTrue( lcr.getConfiguration() instanceof CompositeConfiguration);
+            public void evaluate() throws Throwable {
+                assertTrue(lcr.getConfiguration() instanceof CompositeConfiguration);
             }
         };
-        runTest( lcr, test );
+        runTest(lcr, test);
     }
 
     @Test
-    public void compositeProperties()
-    {
-        final LoggerContextRule lcr =
-            new LoggerContextRule( "classpath:log4j-comp-properties.xml,log4j-comp-properties.json" );
-        Statement test = new Statement()
-        {
+    public void compositeProperties() {
+        final LoggerContextRule lcr = new LoggerContextRule(
+                "classpath:log4j-comp-properties.xml,log4j-comp-properties.json");
+        Statement test = new Statement() {
             @Override
-            public void evaluate()
-                throws Throwable
-            {
+            public void evaluate() throws Throwable {
                 CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
-                assertEquals( "json", config.getStrSubstitutor().replace( "${propertyShared}" ) );
-                assertEquals( "xml", config.getStrSubstitutor().replace( "${propertyXml}" ) );
-                assertEquals( "json", config.getStrSubstitutor().replace( "${propertyJson}" ) );
+                assertEquals("json", config.getStrSubstitutor().replace("${propertyShared}"));
+                assertEquals("xml", config.getStrSubstitutor().replace("${propertyXml}"));
+                assertEquals("json", config.getStrSubstitutor().replace("${propertyJson}"));
             }
         };
-        runTest( lcr, test );
+        runTest(lcr, test);
     }
 
     @Test
-    public void compositeAppenders()
-    {
-        final LoggerContextRule lcr =
-            new LoggerContextRule( "classpath:log4j-comp-appender.xml,log4j-comp-appender.json" );
-        Statement test = new Statement()
-        {
+    public void compositeAppenders() {
+        final LoggerContextRule lcr = new LoggerContextRule(
+                "classpath:log4j-comp-appender.xml,log4j-comp-appender.json");
+        Statement test = new Statement() {
             @Override
-            public void evaluate()
-                throws Throwable
-            {
+            public void evaluate() throws Throwable {
                 CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
                 Map<String, Appender> appender = config.getAppenders();
-                assertEquals( 3, appender.size() );
-                assertTrue( appender.get( "STDOUT" ) instanceof ConsoleAppender );
-                assertTrue( appender.get( "File" ) instanceof FileAppender );
-                assertTrue( appender.get( "Override" ) instanceof RollingFileAppender );
+                assertEquals(3, appender.size());
+                assertTrue(appender.get("STDOUT") instanceof ConsoleAppender);
+                assertTrue(appender.get("File") instanceof FileAppender);
+                assertTrue(appender.get("Override") instanceof RollingFileAppender);
             }
         };
-        runTest( lcr, test );
+        runTest(lcr, test);
     }
 
     @Test
-    public void compositeLogger()
-    {
-        final LoggerContextRule lcr = new LoggerContextRule( "classpath:log4j-comp-logger.xml,log4j-comp-logger.json" );
-        Statement test = new Statement()
-        {
+    public void compositeLogger() {
+        final LoggerContextRule lcr = new LoggerContextRule("classpath:log4j-comp-logger.xml,log4j-comp-logger.json");
+        Statement test = new Statement() {
             @Override
-            public void evaluate()
-                throws Throwable
-            {
+            public void evaluate() throws Throwable {
                 CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
-                Map<String, Appender> appendersMap = config.getLogger( "cat1" ).getAppenders();
+                Map<String, Appender> appendersMap = config.getLogger("cat1").getAppenders();
                 assertEquals("Expected 2 Appender references for cat1 but got " + appendersMap.size(), 2,
-                        appendersMap.size() );
-                assertTrue( appendersMap.get( "STDOUT" ) instanceof ConsoleAppender );
+                        appendersMap.size());
+                assertTrue(appendersMap.get("STDOUT") instanceof ConsoleAppender);
 
-                appendersMap = config.getLogger( "cat2" ).getAppenders();
+                appendersMap = config.getLogger("cat2").getAppenders();
                 assertEquals("Expected 1 Appender reference for cat2 but got " + appendersMap.size(), 1,
-                        appendersMap.size() );
-                assertTrue( appendersMap.get( "File" ) instanceof FileAppender );
+                        appendersMap.size());
+                assertTrue(appendersMap.get("File") instanceof FileAppender);
 
-                appendersMap = config.getLogger( "cat3" ).getAppenders();
+                appendersMap = config.getLogger("cat3").getAppenders();
                 assertEquals("Expected 1 Appender reference for cat3 but got " + appendersMap.size(), 1,
-                        appendersMap.size() );
-                assertTrue( appendersMap.get( "File" ) instanceof FileAppender );
+                        appendersMap.size());
+                assertTrue(appendersMap.get("File") instanceof FileAppender);
 
                 appendersMap = config.getRootLogger().getAppenders();
                 assertEquals("Expected 2 Appender references for the root logger but got " + appendersMap.size(), 2,
-                        appendersMap.size() );
-                assertTrue( appendersMap.get( "File" ) instanceof FileAppender );
-                assertTrue( appendersMap.get( "STDOUT" ) instanceof ConsoleAppender );
+                        appendersMap.size());
+                assertTrue(appendersMap.get("File") instanceof FileAppender);
+                assertTrue(appendersMap.get("STDOUT") instanceof ConsoleAppender);
             }
         };
-        runTest( lcr, test );
+        runTest(lcr, test);
     }
 
     @Test
-    public void overrideFilter()
-    {
-        final LoggerContextRule lcr = new LoggerContextRule( "classpath:log4j-comp-filter.xml,log4j-comp-filter.json" );
-        Statement test = new Statement()
-        {
+    public void overrideFilter() {
+        final LoggerContextRule lcr = new LoggerContextRule("classpath:log4j-comp-filter.xml,log4j-comp-filter.json");
+        Statement test = new Statement() {
             @Override
-            public void evaluate()
-                throws Throwable
-            {
+            public void evaluate() throws Throwable {
                 CompositeConfiguration config = (CompositeConfiguration) lcr.getConfiguration();
-                assertTrue( config.getFilter() instanceof CompositeFilter);
+                assertTrue(config.getFilter() instanceof CompositeFilter);
                 CompositeFilter filter = (CompositeFilter) config.getFilter();
-                assertTrue( filter.getFiltersArray().length == 2);
+                assertTrue(filter.getFiltersArray().length == 2);
             }
         };
-        runTest( lcr, test );
+        runTest(lcr, test);
     }
 
-    private void runTest( LoggerContextRule rule, Statement statement )
-    {
-        try
-        {
-            rule.apply( statement, Description.createTestDescription( getClass(),
-                Thread.currentThread().getStackTrace()[1].getMethodName() ) ).evaluate();
-        }
-        catch ( Throwable throwable )
-        {
-            throw new RuntimeException( throwable );
+    @Test
+    public void testReconfiguration() throws Exception {
+        final LoggerContextRule rule =
+                new LoggerContextRule("classpath:log4j-comp-reconfig.xml,log4j-comp-reconfig.properties");
+        Statement test = new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                final Configuration oldConfig = rule.getConfiguration();
+                final org.apache.logging.log4j.Logger logger = rule.getLogger("LoggerTest");
+                final int MONITOR_INTERVAL_SECONDS = 5;
+                final File file = new File("target/test-classes/log4j-comp-reconfig.properties");
+                final long orig = file.lastModified();
+                final long newTime = orig + 10000;
+                assertTrue("setLastModified should have succeeded.", file.setLastModified(newTime));
+                TimeUnit.SECONDS.sleep(MONITOR_INTERVAL_SECONDS + 1);
+                for (int i = 0; i < 17; ++i) {
+                    logger.debug("Reconfigure");
+                }
+                int loopCount = 0;
+                Configuration newConfig;
+                do {
+                    Thread.sleep(100);
+                    newConfig = rule.getConfiguration();
+                    ++loopCount;
+                } while (newConfig == oldConfig && loopCount <= 5);
+                assertNotSame("Reconfiguration failed", newConfig, oldConfig);
+            }
+        };
+        runTest(rule, test);
+
+    }
+
+    private void runTest(LoggerContextRule rule, Statement statement) {
+        try {
+            rule.apply(statement, Description
+                    .createTestDescription(getClass(), Thread.currentThread().getStackTrace()[1].getMethodName()))
+                    .evaluate();
+        } catch (Throwable throwable) {
+            throw new RuntimeException(throwable);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
index b5a22b1..94e7420 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/config/TestConfigurator.java
@@ -240,7 +240,7 @@ public class TestConfigurator {
         assertNotNull("Appenders map should not be null.", map);
         assertThat(map, hasSize(greaterThan(0)));
         assertThat("Wrong configuration", map, hasKey("List"));
-        
+
         // Sleep and check
         Thread.sleep(50);
         if (!file.setLastModified(System.currentTimeMillis())) {
@@ -251,11 +251,11 @@ public class TestConfigurator {
         for (int i = 0; i < 17; ++i) {
             logger.debug("Test message " + i);
         }
-        
-        // Sleep and check        
-        Thread.sleep(50);            
+
+        // Sleep and check
+        Thread.sleep(50);
         if (is(theInstance(config)).matches(ctx.getConfiguration())) {
-            Thread.sleep(500);            
+            Thread.sleep(500);
         }
         final Configuration newConfig = ctx.getConfiguration();
         assertThat("Configuration not reset", newConfig, is(not(theInstance(config))));
@@ -421,6 +421,7 @@ public class TestConfigurator {
         builder.add( builder.newRootLogger( Level.DEBUG )
                 .add( builder.newAppenderRef( "rolling" ) ) );
         Configuration config = builder.build();
+        config.initialize();
         assertNotNull("No rolling file appender", config.getAppender("rolling"));
         assertEquals("Unexpected Configuration", "RollingBuilder", config.getName());
         // Initialize the new configuration

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/resources/log4j-comp-appender.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-appender.xml b/log4j-core/src/test/resources/log4j-comp-appender.xml
index 7cd71a2..fe71bea 100644
--- a/log4j-core/src/test/resources/log4j-comp-appender.xml
+++ b/log4j-core/src/test/resources/log4j-comp-appender.xml
@@ -16,7 +16,7 @@
  limitations under the License.
 
 -->
-<Configuration status="ERROR" name="XMLConfigTest">
+<Configuration status="ERROR" name="XMLCompositeAppenderTest">
     <Appenders>
         <File name="File" fileName="target/log4j-comp-appender.log" bufferedIO="false">
             <PatternLayout>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/resources/log4j-comp-filter.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-filter.xml b/log4j-core/src/test/resources/log4j-comp-filter.xml
index 553d448..e8f5ae5 100644
--- a/log4j-core/src/test/resources/log4j-comp-filter.xml
+++ b/log4j-core/src/test/resources/log4j-comp-filter.xml
@@ -16,7 +16,7 @@
  limitations under the License.
 
 -->
-<Configuration status="ERROR" name="XMLConfigTest">
+<Configuration status="ERROR" name="XMLCompositeFilterTest">
   <BurstFilter level="INFO" rate="16" maxBurst="100"/>
 
   <Appenders>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/resources/log4j-comp-properties.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-properties.xml b/log4j-core/src/test/resources/log4j-comp-properties.xml
index 6fa9c6b..a896f34 100644
--- a/log4j-core/src/test/resources/log4j-comp-properties.xml
+++ b/log4j-core/src/test/resources/log4j-comp-properties.xml
@@ -16,7 +16,7 @@
  limitations under the License.
 
 -->
-<Configuration status="OFF" name="XMLConfigTest">
+<Configuration status="OFF" name="XMLCompositePropertiesTest">
   <Properties>
     <Property name="propertyShared">xml</Property>
     <Property name="propertyXml">xml</Property>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/resources/log4j-comp-reconfig.properties
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-reconfig.properties b/log4j-core/src/test/resources/log4j-comp-reconfig.properties
new file mode 100644
index 0000000..94f939a
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-reconfig.properties
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+status = error
+name = PropertiesConfigTest
+monitorInterval = 1
+
+property.filename = target/test-properties.log
+
+filter.threshold.type = ThresholdFilter
+filter.threshold.level = debug
+
+appender.console.name = STDOUT
+appender.console.type = Console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %m%n
+
+appender.file.name = File
+appender.file.type = File
+appender.file.fileName = ${filename}
+appender.file.bufferedIO = false
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %p %C{1.} [%t] %m%n
+
+appender.list.name = List
+appender.list.type = List
+appender.list.filter.threshold.type = ThresholdFilter
+appender.list.filter.threshold.level = error
+
+logger.test1.name = org.apache.logging.log4j.test1
+logger.test1.level = debug
+logger.test1.additivity = false
+logger.test1.filter.mdc.type = ThreadContextMapFilter
+logger.test1.filter.mdc.pair.type = KeyValuePair
+logger.test1.filter.mdc.pair.key = test
+logger.test1.filter.mdc.pair.value = 123
+logger.test1.appenderRef.console.ref = STDOUT
+
+logger.test2.name = org.apache.logging.log4j.test2
+logger.test2.level = debug
+logger.test2.additivity = false
+logger.test2.appenderRef.file.ref = File
+
+rootLogger.level = error
+rootLogger.appenderRef.console.ref = STDOUT

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e975a89f/log4j-core/src/test/resources/log4j-comp-reconfig.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/log4j-comp-reconfig.xml b/log4j-core/src/test/resources/log4j-comp-reconfig.xml
new file mode 100644
index 0000000..a0376df
--- /dev/null
+++ b/log4j-core/src/test/resources/log4j-comp-reconfig.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+
+-->
+<Configuration status="ERROR" name="XMLReconfigTest">
+    <Appenders>
+        <File name="File" fileName="target/log4j-comp-appender.log" bufferedIO="false">
+            <PatternLayout>
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+            </PatternLayout>
+        </File>
+        <File name="Override" fileName="target/log4j-comp-appender.log" bufferedIO="false">
+            <PatternLayout>
+                <Pattern>%d %p %C{1.} [%t] %m%n</Pattern>
+            </PatternLayout>
+        </File>
+    </Appenders>
+
+    <Loggers>
+        <Root level="ERROR">
+            <AppenderRef ref="File"/>
+        </Root>
+    </Loggers>
+
+</Configuration>


[03/38] logging-log4j2 git commit: Revert clirr to version 2.6.1. Add composite configuration documentation.

Posted by rg...@apache.org.
Revert clirr to version 2.6.1. Add composite configuration documentation.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/f7909e24
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/f7909e24
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/f7909e24

Branch: refs/heads/master
Commit: f7909e240d11d8eef17d9cfc293eb50daa70b330
Parents: e975a89
Author: Ralph Goers <rg...@nextiva.com>
Authored: Mon Apr 25 18:15:36 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 18:15:36 2016 -0700

----------------------------------------------------------------------
 pom.xml                                   |  2 +-
 src/site/site.xml                         |  1 +
 src/site/xdoc/manual/configuration.xml.vm | 46 +++++++++++++++++++++++---
 3 files changed, 44 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f7909e24/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ac79ff5..df4140d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -210,7 +210,7 @@
     <release.plugin.version>2.5.3</release.plugin.version>
     <scm.plugin.version>1.9.4</scm.plugin.version>
     <jxr.plugin.version>2.5</jxr.plugin.version>
-    <clirr.plugin.version>2.7</clirr.plugin.version>
+    <clirr.plugin.version>2.6.1</clirr.plugin.version>
     <site.plugin.version>3.4</site.plugin.version>
     <manifestfile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestfile>
     <maven.compile.source>1.7</maven.compile.source>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f7909e24/src/site/site.xml
----------------------------------------------------------------------
diff --git a/src/site/site.xml b/src/site/site.xml
index b7f7a35..f9654e5 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -76,6 +76,7 @@
         <item name="Lookup Variables" href="/manual/configuration.html#RuntimeLookup"/>
         <item name="Scripts" href="/manual/configuration.html#Scripts"/>
         <item name="XInclude" href="/manual/configuration.html#XInclude"/>
+        <item name="Composite Configurations" href="/manual/configuration.html#CompositeConfiguration"/>
         <item name="Status Messages" href="/manual/configuration.html#StatusMessages"/>
         <item name="Unit Testing in Maven" href="/manual/configuration.html#UnitTestingInMaven"/>
         <item name="System Properties" href="/manual/configuration.html#SystemProperties"/>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f7909e24/src/site/xdoc/manual/configuration.xml.vm
----------------------------------------------------------------------
diff --git a/src/site/xdoc/manual/configuration.xml.vm b/src/site/xdoc/manual/configuration.xml.vm
index d0525c4..11e5c11 100644
--- a/src/site/xdoc/manual/configuration.xml.vm
+++ b/src/site/xdoc/manual/configuration.xml.vm
@@ -1238,6 +1238,32 @@ rootLogger.appenderRef.stdout.ref = STDOUT
 </loggers>
 ]]></pre>
         </subsection>
+        <a name="CompositeConfiguration"/>
+        <subsection name="Composite Configuration">
+            <p>
+              Log4j allows multiple configuration files to be used by specifying them as a list of comma separated
+              file paths on log4j.configurationFile.  When this is done Log4j will merge the files using the following rules.
+              <ol>
+                <li>The global configuration attributes are aggregated with those in later configurations replacing
+                  those in previous configurations, with the exception that the highest status level and the lowest
+                  monitorInterval greater than 0 will be used.</li>
+                <li>Properties from all configurations are aggregated. Duplicate properties replace those in previous
+                  configurations.</li>
+                <li>Filters are aggregated under a CompositeFilter if more than one Filter is defined. Since Filters
+                  are not named duplicates may be present.</li>
+                <li>Scripts and ScriptFile references are aggregated. Duplicate definiations replace those in previous
+                  configurations.</li>
+                <li>Appenders are aggregated. Appenders with the same name are replaced by those in later
+                  configurations, including all of the Appender's subcomponents.</li>
+                <li>Loggers are all aggregated. Logger attributes are individually merged with duplicates being
+                  replaced by those in later configurations. Appender references on a Logger are aggregated with
+                  duplicates being replaced by those in later configurations. Filters on a Logger are aggregated
+                  under a CompositeFilter if more than one Filter is defined. Since Filters are not named
+                  duplicates may be present. Filters under Appender references included or discarded depending on
+                  whether their parent Appender reference is kept or discarded.</li>
+                </ol>
+            </p>
+        </subsection>
         <a name="StatusMessages"/>
         <subsection name="Status Messages">
           <table>
@@ -1499,12 +1525,15 @@ public class AwesomeTest {
         <a name="SystemProperties"/>
         <subsection name="System Properties">
         <p>
-          Below follows a number of system properties that can be used to control Log4j 2 behaviour.
+          The Log4j documentation references a number of System Properties that can be used to control various aspects
+          of Log4j 2 behavior. The table below lists these properties along with their default value and a
+          description of what they control.
           Any spaces present in the property name are for visual flow and should be removed.
         </p>
           <p>
-            The below properties can also be specified by creating a file named
-            <tt>log4j2.component.properties</tt> and including this file in the classpath of the application.
+            The properties listed below can also be specified by creating a file named
+            <tt>log4j2.component.properties</tt>, adding the desired keys and value to the file, and then including
+            the file in the classpath of the application.
           </p>
 <table>
   <caption align="top">Log4j 2 System Properties</caption>
@@ -1517,7 +1546,16 @@ public class AwesomeTest {
     <td>log4j.configurationFile</td>
     <td>&nbsp;</td>
     <td>
-      Path to an XML or JSON Log4j 2 configuration file.
+      Path to an XML or JSON Log4j 2 configuration file. May also contain a comma separated list of configuration
+      file names.
+    </td>
+  </tr>
+  <tr>
+    <td>log4j.mergeFactory</td>
+    <td>&nbsp;</td>
+    <td>
+      The name of the class that implements the MergeStrategy interface. If not specified
+      <code>DefaultMergeStrategy</code> will be used when creating a CompositeConfiguration..
     </td>
   </tr>
   <tr>


[14/38] logging-log4j2 git commit: LOG4J2-1342 bugfix: don't set ReusableParameterizedMessage array to null

Posted by rg...@apache.org.
LOG4J2-1342 bugfix: don't set ReusableParameterizedMessage array to null


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/fb5e7305
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/fb5e7305
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/fb5e7305

Branch: refs/heads/master
Commit: fb5e7305796d18d7a69ec2ce1a76ad6ae793e77c
Parents: 79e51b2
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 12:50:28 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 .../apache/logging/log4j/core/async/RingBufferLogEvent.java    | 6 ++++--
 .../org/apache/logging/log4j/core/impl/MutableLogEvent.java    | 6 ++++--
 2 files changed, 8 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fb5e7305/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index 72ae8ac..ab5e3d0 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -115,8 +115,10 @@ public class RingBufferLogEvent implements LogEvent, ReusableMessage, CharSequen
         if (msg instanceof ReusableMessage) {
             ReusableMessage reusable = (ReusableMessage) msg;
             reusable.formatTo(getMessageTextForWriting());
-            parameters = reusable.swapParameters(parameters);
-            parameterCount = reusable.getParameterCount();
+            if (parameters != null) {
+                parameters = reusable.swapParameters(parameters);
+                parameterCount = reusable.getParameterCount();
+            }
         } else {
             // if the Message instance is reused, there is no point in freezing its message here
             if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND && msg != null) { // LOG4J2-898: user may choose

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/fb5e7305/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
index 0393b0c..e256723 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/MutableLogEvent.java
@@ -188,8 +188,10 @@ public class MutableLogEvent implements LogEvent, ReusableMessage {
         if (msg instanceof ReusableMessage) {
             ReusableMessage reusable = (ReusableMessage) msg;
             reusable.formatTo(getMessageTextForWriting());
-            parameters = reusable.swapParameters(parameters);
-            parameterCount = reusable.getParameterCount();
+            if (parameters != null) {
+                parameters = reusable.swapParameters(parameters);
+                parameterCount = reusable.getParameterCount();
+            }
         } else {
             // if the Message instance is reused, there is no point in freezing its message here
             if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND && msg != null) { // LOG4J2-898: user may choose


[21/38] logging-log4j2 git commit: LOG4J2-1342 added method ReusableMessage#memento() to take snapshot (used by AsyncAppender)

Posted by rg...@apache.org.
LOG4J2-1342 added method ReusableMessage#memento() to take snapshot (used by AsyncAppender)


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/8f3c146e
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/8f3c146e
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/8f3c146e

Branch: refs/heads/master
Commit: 8f3c146e33039f525eaf1559d200c982c6ebf4cf
Parents: e7fea76
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 14:36:21 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:29 2016 -0700

----------------------------------------------------------------------
 .../org/apache/logging/log4j/message/ReusableMessage.java    | 8 ++++++++
 1 file changed, 8 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8f3c146e/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
index 0536b23..82e40ac 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableMessage.java
@@ -61,4 +61,12 @@ public interface ReusableMessage extends Message, StringBuilderFormattable {
      * @return the current number of parameters
      */
     short getParameterCount();
+
+    /**
+     * Returns an immutable snapshot of the current internal state of this reusable message. The returned snapshot
+     * will not be affected by subsequent modifications of this reusable message.
+     *
+     * @return an immutable snapshot of this message
+     */
+    Message memento();
 }


[04/38] logging-log4j2 git commit: cleanup

Posted by rg...@apache.org.
cleanup


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/d8161086
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/d8161086
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/d8161086

Branch: refs/heads/master
Commit: d8161086890d99226593408172530583a9e00497
Parents: 02cb0fd
Author: rpopma <rp...@apache.org>
Authored: Thu Apr 21 14:34:23 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:27 2016 -0700

----------------------------------------------------------------------
 .../core/async/perftest/SimpleLatencyTest.java  | 30 +-------------------
 1 file changed, 1 insertion(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d8161086/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
index cad4e55..8665d5d 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/async/perftest/SimpleLatencyTest.java
@@ -31,33 +31,6 @@ import org.apache.logging.log4j.core.async.EventRoute;
 
 /**
  * Latency test.
- * <p>
- * See <a href="https://groups.google.com/d/msg/mechanical-sympathy/0gaBXxFm4hE/O9QomwHIJAAJ">https://groups.google.com/d/msg/mechanical-sympathy/0gaBXxFm4hE/O9QomwHIJAAJ</a>:
- * </p>
- * <p>Gil Tene's rules of thumb for latency tests:</p>
- * <ol>
- * <li>DO measure max achievable throughput, but DON'T get focused on it as the main or single axis of measurement /
- * comparison.</li>
- * <li>DO measure response time / latency behaviors across a spectrum of attempted load levels (e.g. at attempted loads
- * between 2% to 100%+ of max established thoughout).</li>
- * <li>DO measure the response time / latency spectrum for each tested load (even for max throughout, for which response
- * time should linearly grow with test length, or the test is wrong). HdrHistogram is one good way to capture this
- * information.</li>
- * <li>DO make sure you are measuring response time correctly and labeling it right. If you also measure and report
- * service time, label it as such (don't call it "latency").
- * <li>DO compare response time / latency spectrum at given loads.</li>
- * <li>DO [repeatedly] sanity check and calibrate the benchmark setup to verify that it produces expected results for
- * known forced scenarios. E.g. forced pauses of known size via ^Z or SIGSTOP/SIGCONT should produce expected response
- * time percentile levels. Attempting to load at >100% than achieved throughput should result in response time / latency
- * measurements that grow with benchmark run length, while service time (if measured) should remain fairly flat well
- * past saturation.</li>
- * <li>DON'T use or report standard deviation for latency. Ever. Except if you mean it as a joke.</li>
- * <li>DON'T use average latency as a way to compare things with one another. [use median or 90%'ile instead, if what
- * you want to compare is "common case" latencies]. Consider not reporting avg. at all.</li>
- * <li>DON'T compare results of different setups or loads from short runs (< 20-30 minutes).</li>
- * <li>DON'T include process warmup behavior (e.g. 1st minute and 1st 50K messages) in compared or reported results.
- * </li>
- * </ol>
  */
 // -DAsyncLogger.WaitStrategy=busywait
 //-XX:+UnlockDiagnosticVMOptions -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime
@@ -69,7 +42,6 @@ public class SimpleLatencyTest {
             System.out.println("Please specify thread count and interval (us)");
             return;
         }
-//        double targetLoadLevel = Double.parseDouble(args[0]);
         final int threadCount = Integer.parseInt(args[0]);
         final int intervalMicros = Integer.parseInt(args[1]);
 
@@ -101,7 +73,7 @@ public class SimpleLatencyTest {
         List<Histogram> histograms = new ArrayList<>(threadCount);
 
         final long TEST_DURATION_MILLIS = TimeUnit.MINUTES.toMillis(4);
-        final int COUNT = 5000000 / threadCount;
+        final int COUNT = (5000 * 1000) / threadCount;
         runLatencyTest(logger, TEST_DURATION_MILLIS, COUNT, interval, idleStrategy, histograms, nanoTimeCost, threadCount);
         long end = System.currentTimeMillis();
 


[07/38] logging-log4j2 git commit: [LOG4J2-1372] XMLLayout indents, but not the first child tag (Event). Javadoc.

Posted by rg...@apache.org.
[LOG4J2-1372] XMLLayout indents, but not the first child tag (Event).
Javadoc.


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/287d2c6b
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/287d2c6b
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/287d2c6b

Branch: refs/heads/master
Commit: 287d2c6b861b2f938d0bb9dcebd897681bfb3520
Parents: 1d12bf0
Author: ggregory <gg...@apache.org>
Authored: Wed Apr 20 10:21:53 2016 -0700
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:27 2016 -0700

----------------------------------------------------------------------
 .../org/apache/logging/log4j/core/layout/JacksonFactory.java     | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/287d2c6b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
index 3b34957..ea0877f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
@@ -144,12 +144,14 @@ abstract class JacksonFactory {
 
     /**
      * When &lt;Event&gt;s are written into a XML file; the "Event" object is not the root element, but an element named
-     * &lt;Events&gt; created using {@link #getHeader()} and {@link #getFooter()} methods.<br/>
+     * &lt;Events&gt; created using {@link XmlLayout#getHeader()} and {@link XmlLayout#getFooter()} methods.
+     * <p>
      * {@link com.fasterxml.jackson.dataformat.xml.util.DefaultXmlPrettyPrinter} is used to print the Event object into
      * XML; hence it assumes &lt;Event&gt; tag as the root element, so it prints the &lt;Event&gt; tag without any
      * indentation. To add an indentation to the &lt;Event&gt; tag; hence an additional indentation for any
      * sub-elements, this class is written. As an additional task, to avoid the blank line printed after the ending
      * &lt;/Event&gt; tag, {@link #writePrologLinefeed(XMLStreamWriter2)} method is also overridden.
+     * </p>
      */
     static class Log4jXmlPrettyPrinter extends DefaultXmlPrettyPrinter {
 


[34/38] logging-log4j2 git commit: LOG4J2-1373 updated change log

Posted by rg...@apache.org.
LOG4J2-1373 updated change log


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/2db215b7
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/2db215b7
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/2db215b7

Branch: refs/heads/master
Commit: 2db215b7bfa080aa83e6c9a805c0cfc2b1e72aa0
Parents: be8779b
Author: rpopma <rp...@apache.org>
Authored: Sat Apr 23 15:42:43 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:30 2016 -0700

----------------------------------------------------------------------
 src/changes/changes.xml | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/2db215b7/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 0edfea6..4c23f35 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,9 @@
   </properties>
   <body>
     <release version="2.6" date="2016-MM-DD" description="GA Release 2.6">
+      <action issue="LOG4J2-1373" dev="rpopma" type="add">
+        (GC) Update Logger wrapper Generator tool to generate methods for the new Logger methods.
+      </action>
       <action issue="LOG4J2-1372" dev="rgoers" type="fix" due-to="Kamal Mettananda, Gary Gregory">
         XMLLayout indents, but not the first child tag (Event).
       </action>


[16/38] logging-log4j2 git commit: LOG4J2-1342 added tests to verify parameters are passed correctly with async logging

Posted by rg...@apache.org.
LOG4J2-1342 added tests to verify parameters are passed correctly with async logging


Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/873e19b4
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/873e19b4
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/873e19b4

Branch: refs/heads/master
Commit: 873e19b4258032a253cc5baee03b4919fc170397
Parents: 6ef68fa
Author: rpopma <rp...@apache.org>
Authored: Fri Apr 22 12:08:38 2016 +0900
Committer: Ralph Goers <rg...@nextiva.com>
Committed: Mon Apr 25 21:30:28 2016 -0700

----------------------------------------------------------------------
 .../layout/CsvParameterLayoutAllAsyncTest.java  | 69 ++++++++++++++++++
 .../core/layout/CsvParameterLayoutTest.java     | 73 ++++++++++++--------
 .../src/test/resources/csvParamsMixedAsync.xml  | 13 ++++
 log4j-core/src/test/resources/csvParamsSync.xml | 29 ++++++++
 4 files changed, 156 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/873e19b4/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutAllAsyncTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutAllAsyncTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutAllAsyncTest.java
new file mode 100644
index 0000000..0ef2e1d
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutAllAsyncTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+package org.apache.logging.log4j.core.layout;
+
+import org.apache.commons.csv.CSVFormat;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.Logger;
+import org.apache.logging.log4j.core.async.AsyncLoggerContextSelector;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.junit.LoggerContextRule;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests {@link AbstractCsvLayout} with all loggers async.
+ *
+ * @since 2.6
+ */
+public class CsvParameterLayoutAllAsyncTest {
+
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR,
+                AsyncLoggerContextSelector.class.getName());
+        System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+                "AsyncLoggerTest.xml");
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, Strings.EMPTY);
+    }
+
+
+    @Test
+    public void testLayoutDefaultNormal() throws Exception {
+        Logger root = (Logger) LogManager.getRootLogger();
+        CsvParameterLayoutTest.testLayoutNormalApi(root, CsvParameterLayout.createDefaultLayout(), false);
+    }
+
+    @Test
+    public void testLayoutDefaultObjectArrayMessage() throws Exception {
+        Logger root = (Logger) LogManager.getRootLogger();
+        CsvParameterLayoutTest.testLayoutNormalApi(root, CsvParameterLayout.createDefaultLayout(), true);
+    }
+
+    @Test
+    public void testLayoutTab() throws Exception {
+        Logger root = (Logger) LogManager.getRootLogger();
+        CsvParameterLayoutTest.testLayoutNormalApi(root, CsvParameterLayout.createLayout(CSVFormat.TDF), true);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/873e19b4/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
index 5f58d79..ce3abfc 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvParameterLayoutTest.java
@@ -16,9 +16,9 @@
  */
 package org.apache.logging.log4j.core.layout;
 
-import static org.junit.Assert.assertEquals;
-
 import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -26,43 +26,49 @@ import org.apache.commons.csv.CSVFormat;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.BasicConfigurationFactory;
 import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.junit.LoggerContextRule;
 import org.apache.logging.log4j.message.ObjectArrayMessage;
 import org.apache.logging.log4j.test.appender.ListAppender;
 import org.junit.AfterClass;
 import org.junit.Assert;
-import org.junit.BeforeClass;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.*;
 
 /**
  * Tests {@link AbstractCsvLayout}.
  *
  * @since 2.4
  */
+@RunWith(value = Parameterized.class)
 public class CsvParameterLayoutTest {
-    static ConfigurationFactory cf = new BasicConfigurationFactory();
+    @Parameterized.Parameters(name = "{0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][]{
+                        { new LoggerContextRule("csvParamsSync.xml"), },
+                        { new LoggerContextRule("csvParamsMixedAsync.xml"), },
+                }
+        );
+    }
 
-    @AfterClass
-    public static void cleanupClass() {
-        ConfigurationFactory.removeConfigurationFactory(cf);
-        ThreadContext.clearAll();
+    @Rule
+    public final LoggerContextRule init;
+
+    public CsvParameterLayoutTest(final LoggerContextRule contextRule) {
+        this.init = contextRule;
     }
 
-    @BeforeClass
-    public static void setupClass() {
+    @AfterClass
+    public static void cleanupClass() {
+//        System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, null);
         ThreadContext.clearAll();
-        ConfigurationFactory.setConfigurationFactory(cf);
-        final LoggerContext ctx = LoggerContext.getContext();
-        ctx.reconfigure();
     }
 
-    private final LoggerContext ctx = LoggerContext.getContext();
-
-    private final Logger root = ctx.getLogger("");
-
     @Test
     public void testCustomCharset() {
         final AbstractCsvLayout layout = CsvParameterLayout.createLayout(null, "Excel", null, null, null, null, null,
@@ -82,7 +88,7 @@ public class CsvParameterLayoutTest {
         assertEquals("text/csv; charset=UTF-8", layout.getContentType());
     }
 
-    private void testLayoutNormalApi(final AbstractCsvLayout layout, boolean messageApi) throws Exception {
+    static void testLayoutNormalApi(final Logger root, final AbstractCsvLayout layout, boolean messageApi) throws Exception {
         final Map<String, Appender> appenders = root.getAppenders();
         for (final Appender appender : appenders.values()) {
             root.removeAppender(appender);
@@ -97,11 +103,19 @@ public class CsvParameterLayoutTest {
 
         // output messages
         if (messageApi) {
-            logDebugObjectArrayMessage();
+            logDebugObjectArrayMessage(root);
         } else {
-            logDebugNormalApi();
+            logDebugNormalApi(root);
+        }
+
+        // wait until background thread finished processing
+        int maxTries = 50;
+        while (appender.getMessages().size() < 4 && maxTries-- > 0) {
+            Thread.sleep(1L);
         }
+        assertEquals("Background thread did not finish processing: msg count", 4, appender.getMessages().size());
 
+        // don't stop appender until background thread is done
         appender.stop();
 
         final List<String> list = appender.getMessages();
@@ -112,14 +126,14 @@ public class CsvParameterLayoutTest {
         Assert.assertEquals("7" + d + "8" + d + "9" + d + "10", list.get(3));
     }
 
-    private void logDebugNormalApi() {
+    private static void logDebugNormalApi(final Logger root) {
         root.debug("with placeholders: {}{}{}", 1, 2, 3);
         root.debug("without placeholders", 2, 3);
         root.debug(null, 5, 6);
         root.debug("invalid placeholder count {}", 7, 8, 9, 10);
     }
 
-    private void logDebugObjectArrayMessage() {
+    private static void logDebugObjectArrayMessage(final Logger root) {
         root.debug(new ObjectArrayMessage(1, 2, 3));
         root.debug(new ObjectArrayMessage(2, 3));
         root.debug(new ObjectArrayMessage(5, 6));
@@ -128,16 +142,19 @@ public class CsvParameterLayoutTest {
 
     @Test
     public void testLayoutDefaultNormal() throws Exception {
-        testLayoutNormalApi(CsvParameterLayout.createDefaultLayout(), false);
+        Logger root = this.init.getLogger("");
+        testLayoutNormalApi(root, CsvParameterLayout.createDefaultLayout(), false);
     }
 
     @Test
     public void testLayoutDefaultObjectArrayMessage() throws Exception {
-        testLayoutNormalApi(CsvParameterLayout.createDefaultLayout(), true);
+        Logger root = this.init.getLogger("");
+        testLayoutNormalApi(root, CsvParameterLayout.createDefaultLayout(), true);
     }
 
     @Test
     public void testLayoutTab() throws Exception {
-        testLayoutNormalApi(CsvParameterLayout.createLayout(CSVFormat.TDF), true);
+        Logger root = this.init.getLogger("");
+        testLayoutNormalApi(root, CsvParameterLayout.createLayout(CSVFormat.TDF), true);
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/873e19b4/log4j-core/src/test/resources/csvParamsMixedAsync.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/csvParamsMixedAsync.xml b/log4j-core/src/test/resources/csvParamsMixedAsync.xml
new file mode 100644
index 0000000..4d0811a
--- /dev/null
+++ b/log4j-core/src/test/resources/csvParamsMixedAsync.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="OFF">
+  <Appenders>
+    <List name="List">
+      <PatternLayout pattern="[%-5level] %c{1.} %msg%n" />
+    </List>
+  </Appenders>
+  <Loggers>
+    <AsyncRoot level="debug" includeLocation="false">
+      <appender-ref ref="List"/>
+    </AsyncRoot>
+  </Loggers>
+</Configuration>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/873e19b4/log4j-core/src/test/resources/csvParamsSync.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/csvParamsSync.xml b/log4j-core/src/test/resources/csvParamsSync.xml
new file mode 100644
index 0000000..c2a92c3
--- /dev/null
+++ b/log4j-core/src/test/resources/csvParamsSync.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<Configuration status="WARN">
+  <Appenders>
+    <List name="List">
+      <PatternLayout pattern="[%-5level] %c{1.} %msg%n" />
+    </List>
+  </Appenders>
+  <Loggers>
+    <Root level="debug">
+      <AppenderRef ref="List" />
+    </Root>
+  </Loggers>
+</Configuration>
\ No newline at end of file