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

[1/4] logging-log4j2 git commit: [LOG4J2-1362] Create a YAML layout.

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 3c37ca34d -> ffbd8c9b2


[LOG4J2-1362] Create a YAML layout.

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

Branch: refs/heads/master
Commit: 80a43988a017a8e95f6188386cd5fe7ddf3945bd
Parents: 71fbda8
Author: ggregory <gg...@apache.org>
Authored: Sun Apr 17 15:27:19 2016 -0700
Committer: ggregory <gg...@apache.org>
Committed: Sun Apr 17 15:27:19 2016 -0700

----------------------------------------------------------------------
 .../org/apache/logging/log4j/util/Strings.java  |  12 +
 .../log4j/core/jackson/Log4jYamlModule.java     |  48 ++++
 .../core/jackson/Log4jYamlObjectMapper.java     |  41 +++
 .../log4j/core/layout/JacksonFactory.java       |  34 +++
 .../logging/log4j/core/layout/YamlLayout.java   | 193 +++++++++++++
 .../logging/log4j/MarkerMixInYamlTest.java      |  31 ++
 .../log4j/core/jackson/LevelMixInYamlTest.java  |  29 ++
 .../jackson/StackTraceElementMixInTest.java     |   5 +
 .../log4j/core/layout/YamlLayoutTest.java       | 287 +++++++++++++++++++
 .../log4j/web/ServletRequestThreadContext.java  |  29 ++
 10 files changed, 709 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-api/src/main/java/org/apache/logging/log4j/util/Strings.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Strings.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/Strings.java
index 6ee7dca..294b771 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Strings.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Strings.java
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.util;
 
+import java.util.Locale;
+
 /**
  * <em>Consider this class private.</em>
  * 
@@ -127,6 +129,16 @@ public final class Strings {
     }
 
     /**
+     * Shorthand for {@code str.toUpperCase(Locale.ROOT);}
+     * @param str The string to upper case.
+     * @return a new string
+     * @see String#toLowerCase(Locale)
+     */
+    public String toRootUpperCase(final String str) {
+        return str.toUpperCase(Locale.ROOT);
+    }
+    
+    /**
      * <p>
      * Removes control characters (char &lt;= 32) from both ends of this String returning {@code null} if the String is
      * empty ("") after the trim or if it is {@code null}.

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java
new file mode 100644
index 0000000..4052320
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlModule.java
@@ -0,0 +1,48 @@
+/*
+ * 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.jackson;
+
+import org.apache.logging.log4j.core.jackson.Initializers.SetupContextInitializer;
+import org.apache.logging.log4j.core.jackson.Initializers.SimpleModuleInitializer;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+/**
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+final class Log4jYamlModule extends SimpleModule {
+
+    private static final long serialVersionUID = 1L;
+
+    Log4jYamlModule() {
+        super(Log4jYamlModule.class.getName(), new Version(2, 0, 0, null, null, null));
+        // MUST init here.
+        // Calling this from setupModule is too late!
+        //noinspection ThisEscapedInObjectConstruction
+        new SimpleModuleInitializer().initialize(this);
+    }
+
+    @Override
+    public void setupModule(final SetupContext context) {
+        // Calling super is a MUST!
+        super.setupModule(context);
+        new SetupContextInitializer().setupModule(context);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java
new file mode 100644
index 0000000..9ab787a
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/jackson/Log4jYamlObjectMapper.java
@@ -0,0 +1,41 @@
+/*
+ * 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.jackson;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
+
+/**
+ * A Jackson {@link ObjectMapper} initialized for Log4j.
+ * <p>
+ * <em>Consider this class private.</em>
+ * </p>
+ */
+public class Log4jYamlObjectMapper extends YAMLMapper {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Create a new instance using the {@link Log4jYamlModule}.
+     */
+    public Log4jYamlObjectMapper() {
+        this.registerModule(new Log4jYamlModule());
+        this.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/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 537b634..44731f4 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
@@ -23,6 +23,7 @@ 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 com.fasterxml.jackson.core.PrettyPrinter;
@@ -103,6 +104,39 @@ abstract class JacksonFactory {
         }
     }
 
+    static class YAML extends JacksonFactory {
+
+        @Override
+        protected String getPropertNameForContextMap() {
+            return JsonConstants.ELT_CONTEXT_MAP;
+        }
+
+        @Override
+        protected String getPropertNameForSource() {
+            return JsonConstants.ELT_SOURCE;
+        }
+
+        @Override
+        protected String getPropertNameForNanoTime() {
+            return JsonConstants.ELT_NANO_TIME;
+        }
+
+        @Override
+        protected PrettyPrinter newCompactPrinter() {
+            return new MinimalPrettyPrinter();
+        }
+
+        @Override
+        protected ObjectMapper newObjectMapper() {
+            return new Log4jYamlObjectMapper();
+        }
+
+        @Override
+        protected PrettyPrinter newPrettyPrinter() {
+            return new DefaultPrettyPrinter();
+        }
+    }
+
     abstract protected String getPropertNameForContextMap();
 
     abstract protected String getPropertNameForSource();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
new file mode 100644
index 0000000..0426fea
--- /dev/null
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
@@ -0,0 +1,193 @@
+/*
+ * 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 java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.DefaultConfiguration;
+import org.apache.logging.log4j.core.config.Node;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+
+/**
+ * Appends a series of YAML events as strings serialized as bytes.
+ *
+ * <h3>Complete well-formed YAML vs. fragment YAML</h3>
+ * <p>
+ * If you configure {@code complete="true"}, the appender outputs a well-formed YAML document. By default, with
+ * {@code complete="false"}, you should include the output as an <em>external file</em> in a separate file to form a
+ * well-formed YAML document.
+ * </p>
+ * <p>
+ * A well-formed YAML event follows this pattern:
+ * </p>
+ *
+ * <pre>
+ * 
+ * </pre>
+ * <p>
+ * If {@code complete="false"}, the appender does not write the YAML open array character "[" at the start of the
+ * document, "]" and the end, nor comma "," between records.
+ * </p>
+ * <p>
+ * This approach enforces the independence of the YamlLayout and the appender where you embed it.
+ * </p>
+ * <h3>Encoding</h3>
+ * <p>
+ * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
+ * events containing non ASCII characters could result in corrupted log files.
+ * </p>
+ * <h3>Pretty vs. compact YAML</h3>
+ * <p>
+ * By default, the YAML layout is not compact (a.k.a. "pretty") with {@code compact="false"}, which means the appender
+ * uses end-of-line characters and indents lines to format the text. If {@code compact="true"}, then no end-of-line or
+ * indentation is used. Message content may contain, of course, escaped end-of-lines.
+ * </p>
+ */
+@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
+public final class YamlLayout extends AbstractJacksonLayout {
+
+    private static final String DEFAULT_FOOTER = ""; // TODO maybe
+
+    private static final String DEFAULT_HEADER = ""; // TODO maybe
+
+    static final String CONTENT_TYPE = "application/yaml";
+
+    protected YamlLayout(final Configuration config, final boolean locationInfo, final boolean properties,
+            final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
+            final String footerPattern, final Charset charset) {
+        super(config, new JacksonFactory.YAML().newWriter(locationInfo, properties, compact), charset, compact,
+                complete, eventEol,
+                PatternLayout.createSerializer(config, null, headerPattern, DEFAULT_HEADER, null, false, false),
+                PatternLayout.createSerializer(config, null, footerPattern, DEFAULT_FOOTER, null, false, false));
+    }
+
+    /**
+     * Returns appropriate YAML header.
+     *
+     * @return a byte array containing the header, opening the YAML array.
+     */
+    @Override
+    public byte[] getHeader() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        final String str = serializeToString(getHeaderSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
+        buf.append(this.eol);
+        return getBytes(buf.toString());
+    }
+
+    /**
+     * Returns appropriate YAML footer.
+     *
+     * @return a byte array containing the footer, closing the YAML array.
+     */
+    @Override
+    public byte[] getFooter() {
+        if (!this.complete) {
+            return null;
+        }
+        final StringBuilder buf = new StringBuilder();
+        buf.append(this.eol);
+        final String str = serializeToString(getFooterSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
+        buf.append(this.eol);
+        return getBytes(buf.toString());
+    }
+
+    @Override
+    public Map<String, String> getContentFormat() {
+        final Map<String, String> result = new HashMap<>();
+        result.put("version", "2.0");
+        return result;
+    }
+
+    @Override
+    /**
+     * @return The content type.
+     */
+    public String getContentType() {
+        return CONTENT_TYPE + "; charset=" + this.getCharset();
+    }
+
+    /**
+     * Creates a YAML Layout.
+     * 
+     * @param config
+     *            The plugin configuration.
+     * @param locationInfo
+     *            If "true", includes the location information in the generated YAML.
+     * @param properties
+     *            If "true", includes the thread context in the generated YAML.
+     * @param headerPattern
+     *            The header pattern, defaults to {@code ""} if null.
+     * @param footerPattern
+     *            The header pattern, defaults to {@code ""} if null.
+     * @param footerPattern
+     * @param charset
+     *            The character set to use, if {@code null}, uses "UTF-8".
+     * @return A YAML Layout.
+     */
+    @PluginFactory
+    public static AbstractJacksonLayout createLayout(
+            // @formatter:off
+            @PluginConfiguration final Configuration config,
+            @PluginAttribute(value = "locationInfo", defaultBoolean = false) final boolean locationInfo,
+            @PluginAttribute(value = "properties", defaultBoolean = false) final boolean properties,
+            @PluginAttribute(value = "header", defaultString = DEFAULT_HEADER) final String headerPattern,
+            @PluginAttribute(value = "footer", defaultString = DEFAULT_FOOTER) final String footerPattern,
+            @PluginAttribute(value = "charset", defaultString = "UTF-8") final Charset charset
+            // @formatter:on
+    ) {
+        return new YamlLayout(config, locationInfo, properties, false, false, true, headerPattern, footerPattern,
+                charset);
+    }
+
+    /**
+     * Creates a YAML Layout using the default settings. Useful for testing.
+     *
+     * @return A YAML Layout.
+     */
+    public static AbstractJacksonLayout createDefaultLayout() {
+        return new YamlLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER,
+                DEFAULT_FOOTER, StandardCharsets.UTF_8);
+    }
+
+    @Override
+    public void toSerializable(final LogEvent event, final Writer writer) throws IOException {
+        if (complete && eventCount > 0) {
+            writer.append(", ");
+        }
+        super.toSerializable(event, writer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java
new file mode 100644
index 0000000..89f02a1
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/MarkerMixInYamlTest.java
@@ -0,0 +1,31 @@
+/*
+* 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;
+
+import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class MarkerMixInYamlTest extends MarkerMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jYamlObjectMapper();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java
new file mode 100644
index 0000000..cff034e
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/LevelMixInYamlTest.java
@@ -0,0 +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.jackson;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class LevelMixInYamlTest extends LevelMixInTest {
+
+    @Override
+    protected ObjectMapper newObjectMapper() {
+        return new Log4jYamlObjectMapper();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
index ed9b3da..5f3383b 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/jackson/StackTraceElementMixInTest.java
@@ -34,6 +34,11 @@ public class StackTraceElementMixInTest {
         this.roundtrip(new Log4jJsonObjectMapper());
     }
 
+    @Test
+    public void testLog4jYamlObjectMapper() throws Exception {
+        this.roundtrip(new Log4jYamlObjectMapper());
+    }
+
     /**
      * @param mapper
      * @throws JsonProcessingException

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
new file mode 100644
index 0000000..fd30bbd
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/YamlLayoutTest.java
@@ -0,0 +1,287 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+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.Configuration;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.jackson.Log4jYamlObjectMapper;
+import org.apache.logging.log4j.message.SimpleMessage;
+import org.apache.logging.log4j.spi.AbstractLogger;
+import org.apache.logging.log4j.test.appender.ListAppender;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests the YamlLayout class.
+ */
+public class YamlLayoutTest {
+    static ConfigurationFactory cf = new BasicConfigurationFactory();
+
+    private static final String DQUOTE = "\"";
+
+    @AfterClass
+    public static void cleanupClass() {
+        ConfigurationFactory.removeConfigurationFactory(cf);
+        ThreadContext.clearAll();
+    }
+
+    @BeforeClass
+    public static void setupClass() {
+        ThreadContext.clearAll();
+        ConfigurationFactory.setConfigurationFactory(cf);
+        final LoggerContext ctx = LoggerContext.getContext();
+        ctx.reconfigure();
+    }
+
+    LoggerContext ctx = LoggerContext.getContext();
+
+    Logger rootLogger = this.ctx.getLogger("");
+
+    private void checkAt(final String expected, final int lineIndex, final List<String> list) {
+        final String trimedLine = list.get(lineIndex).trim();
+        assertTrue("Incorrect line index " + lineIndex + ": " + Strings.dquote(trimedLine),
+                trimedLine.equals(expected));
+    }
+
+    private void checkContains(final String expected, final List<String> list) {
+        for (final String string : list) {
+            final String trimedLine = string.trim();
+            if (trimedLine.equals(expected)) {
+                return;
+            }
+        }
+        Assert.fail("Cannot find " + expected + " in " + list);
+    }
+
+    private void checkMapEntry(final String key, final String value, final boolean compact, final String str) {
+        final String propSep = this.toPropertySeparator(compact, true);
+        // "name":"value"
+        final String expected = String.format("- key: \"%s\"\n  value: \"%s\"", key, value);
+        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
+    }
+
+    private void checkProperty(final String key, final String value, final boolean compact, final String str,
+            final boolean isValue) {
+        final String propSep = this.toPropertySeparator(compact, isValue);
+        // {"key":"MDC.B","value":"B_Value"}
+        final String expected = String.format("%s%s\"%s\"", key, propSep, value);
+        assertTrue("Cannot find " + expected + " in " + str, str.contains(expected));
+    }
+
+    private void checkPropertyName(final String name, final boolean compact, final String str, final boolean isValue) {
+        final String propSep = this.toPropertySeparator(compact, isValue);
+        assertTrue(str, str.contains(name + propSep));
+    }
+
+    private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean eventEol,
+            final boolean includeContext) throws Exception {
+        final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
+        final AbstractJacksonLayout layout = YamlLayout.createLayout(null, includeSource, includeContext, null, null,
+                StandardCharsets.UTF_8);
+        final String str = layout.toSerializable(expected);
+        // System.out.println(str);
+        final String propSep = this.toPropertySeparator(compact, true);
+        // Just check for \n since \r might or might not be there.
+        assertEquals(str, !compact || eventEol, str.contains("\n"));
+        assertEquals(str, includeSource, str.contains("source"));
+        assertEquals(str, includeContext, str.contains("contextMap"));
+        final Log4jLogEvent actual = new Log4jYamlObjectMapper().readValue(str, Log4jLogEvent.class);
+        LogEventFixtures.assertEqualLogEvents(expected, actual, includeSource, includeContext);
+        if (includeContext) {
+            this.checkMapEntry("MDC.A", "A_Value", compact, str);
+            this.checkMapEntry("MDC.B", "B_Value", compact, str);
+        }
+        //
+        assertNull(actual.getThrown());
+        // make sure the names we want are used
+        this.checkPropertyName("timeMillis", compact, str, true);
+        this.checkPropertyName("thread", compact, str, true); // and not threadName
+        this.checkPropertyName("level", compact, str, true);
+        this.checkPropertyName("loggerName", compact, str, true);
+        this.checkPropertyName("marker", compact, str, false);
+        this.checkPropertyName("name", compact, str, true);
+        this.checkPropertyName("parents", compact, str, false);
+        this.checkPropertyName("message", compact, str, true);
+        this.checkPropertyName("thrown", compact, str, false);
+        this.checkPropertyName("cause", compact, str, false);
+        this.checkPropertyName("class", compact, str, true);
+        this.checkPropertyName("method", compact, str, true);
+        this.checkPropertyName("file", compact, str, true);
+        this.checkPropertyName("line", compact, str, true);
+        this.checkPropertyName("exact", compact, str, true);
+        this.checkPropertyName("location", compact, str, true);
+        this.checkPropertyName("version", compact, str, true);
+        this.checkPropertyName("commonElementCount", compact, str, true);
+        this.checkPropertyName("localizedMessage", compact, str, true);
+        this.checkPropertyName("extendedStackTrace", compact, str, false);
+        this.checkPropertyName("suppressed", compact, str, false);
+        this.checkPropertyName("loggerFqcn", compact, str, true);
+        this.checkPropertyName("endOfBatch", compact, str, true);
+        if (includeContext) {
+            this.checkPropertyName("contextMap", compact, str, false);
+        }
+        this.checkPropertyName("contextStack", compact, str, false);
+        if (includeSource) {
+            this.checkPropertyName("source", compact, str, false);
+        }
+        // check some attrs
+        this.checkProperty("loggerFqcn", "f.q.c.n", compact, str, true);
+        this.checkProperty("loggerName", "a.B", compact, str, true);
+    }
+
+    @Test
+    public void testContentType() {
+        final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout();
+        assertEquals("application/yaml; charset=UTF-8", layout.getContentType());
+    }
+
+    @Test
+    public void testDefaultCharset() {
+        final AbstractJacksonLayout layout = YamlLayout.createDefaultLayout();
+        assertEquals(StandardCharsets.UTF_8, layout.getCharset());
+    }
+
+    @Test
+    public void testEscapeLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
+        // set up appender
+        final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, null, null, null);
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("Here is a quote ' and then a double quote \"");
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        this.checkAt("---", 0, list);
+        this.checkContains("level: \"DEBUG\"", list);
+        this.checkContains("message: \"Here is a quote ' and then a double quote \\\"\"", list);
+        this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list);
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    /**
+     * Test case for MDC conversion pattern.
+     */
+    @Test
+    public void testLayout() throws Exception {
+        final Map<String, Appender> appenders = this.rootLogger.getAppenders();
+        for (final Appender appender : appenders.values()) {
+            this.rootLogger.removeAppender(appender);
+        }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
+        // set up appender
+        // Use [[ and ]] to test header and footer (instead of [ and ])
+        final AbstractJacksonLayout layout = YamlLayout.createLayout(configuration, true, true, "[[", "]]", null);
+        final ListAppender appender = new ListAppender("List", null, layout, true, false);
+        appender.start();
+
+        // set appender on root and set level to debug
+        this.rootLogger.addAppender(appender);
+        this.rootLogger.setLevel(Level.DEBUG);
+
+        // output starting message
+        this.rootLogger.debug("starting mdc pattern test");
+
+        this.rootLogger.debug("empty mdc");
+
+        ThreadContext.put("key1", "value1");
+        ThreadContext.put("key2", "value2");
+
+        this.rootLogger.debug("filled mdc");
+
+        ThreadContext.remove("key1");
+        ThreadContext.remove("key2");
+
+        this.rootLogger.error("finished mdc pattern test", new NullPointerException("test"));
+
+        appender.stop();
+
+        final List<String> list = appender.getMessages();
+
+        this.checkAt("---", 0, list);
+        this.checkContains("loggerFqcn: \"" + AbstractLogger.class.getName() + "\"", list);
+        this.checkContains("level: \"DEBUG\"", list);
+        this.checkContains("message: \"starting mdc pattern test\"", list);
+        for (final Appender app : appenders.values()) {
+            this.rootLogger.addAppender(app);
+        }
+    }
+
+    @Test
+    public void testLayoutLoggerName() throws Exception {
+        final AbstractJacksonLayout layout = YamlLayout.createLayout(null, false, false, null, null,
+                StandardCharsets.UTF_8);
+        final Log4jLogEvent expected = Log4jLogEvent.newBuilder() //
+                .setLoggerName("a.B") //
+                .setLoggerFqcn("f.q.c.n") //
+                .setLevel(Level.DEBUG) //
+                .setMessage(new SimpleMessage("M")) //
+                .setThreadName("threadName") //
+                .setTimeMillis(1).build();
+        final String str = layout.toSerializable(expected);
+        assertTrue(str, str.contains("loggerName: \"a.B\""));
+        final Log4jLogEvent actual = new Log4jYamlObjectMapper().readValue(str, Log4jLogEvent.class);
+        assertEquals(expected.getLoggerName(), actual.getLoggerName());
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testLocationOffCompactOffMdcOff() throws Exception {
+        this.testAllFeatures(false, false, false, false);
+    }
+
+    @Test
+    public void testLocationOnCompactOffEventEolOffMdcOn() throws Exception {
+        this.testAllFeatures(true, false, false, true);
+    }
+
+    private String toPropertySeparator(final boolean compact, final boolean value) {
+        return value ? ": " : ":";
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/80a43988/log4j-web/src/main/java/org/apache/logging/log4j/web/ServletRequestThreadContext.java
----------------------------------------------------------------------
diff --git a/log4j-web/src/main/java/org/apache/logging/log4j/web/ServletRequestThreadContext.java b/log4j-web/src/main/java/org/apache/logging/log4j/web/ServletRequestThreadContext.java
new file mode 100644
index 0000000..6615531
--- /dev/null
+++ b/log4j-web/src/main/java/org/apache/logging/log4j/web/ServletRequestThreadContext.java
@@ -0,0 +1,29 @@
+package org.apache.logging.log4j.web;
+
+import java.util.Objects;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.logging.log4j.ThreadContext;
+
+public class ServletRequestThreadContext {
+
+    public static void put(String key, ServletRequest servletRequest) {
+        put(key, "RemoteAddr", servletRequest.getRemoteAddr());
+        put(key, "RemoteHost", servletRequest.getRemoteHost());
+        put(key, "RemotePort", servletRequest.getRemotePort());
+    }
+
+    public static void put(String key, String field, Object value) {
+        put(key + "." + field, Objects.toString(value));
+    }
+
+    public static void put(String key, String value) {
+        ThreadContext.put(key, value);
+    }
+
+    public static void put(String key, HttpServletRequest servletRequest) {
+        put(key, (ServletRequest) servletRequest);
+    }
+}


[4/4] logging-log4j2 git commit: [LOG4J2-1362] Create a YAML layout.

Posted by gg...@apache.org.
[LOG4J2-1362] Create a YAML layout.

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

Branch: refs/heads/master
Commit: ffbd8c9b2268815449b3b5321cdbf936395d34f1
Parents: 5114233
Author: ggregory <gg...@apache.org>
Authored: Sun Apr 17 16:07:40 2016 -0700
Committer: ggregory <gg...@apache.org>
Committed: Sun Apr 17 16:07:40 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/core/layout/YamlLayout.java   | 677 ++++++++++++++++++-
 .../appender/JsonCompleteFileAppenderTest.java  |   2 +-
 src/site/site.xml                               |   1 +
 src/site/xdoc/manual/layouts.xml.vm             | 151 +++++
 4 files changed, 807 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ffbd8c9b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
index 0426fea..b68b836 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/YamlLayout.java
@@ -32,27 +32,664 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
 import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.util.Strings;
 
 /**
  * Appends a series of YAML events as strings serialized as bytes.
  *
- * <h3>Complete well-formed YAML vs. fragment YAML</h3>
  * <p>
- * If you configure {@code complete="true"}, the appender outputs a well-formed YAML document. By default, with
- * {@code complete="false"}, you should include the output as an <em>external file</em> in a separate file to form a
- * well-formed YAML document.
- * </p>
- * <p>
- * A well-formed YAML event follows this pattern:
+ * A YAML log event follows this pattern:
  * </p>
  *
- * <pre>
- * 
- * </pre>
- * <p>
- * If {@code complete="false"}, the appender does not write the YAML open array character "[" at the start of the
- * document, "]" and the end, nor comma "," between records.
- * </p>
+ * <pre>---
+timeMillis: 1
+thread: "MyThreadName"
+level: "DEBUG"
+loggerName: "a.B"
+marker:
+  name: "Marker1"
+  parents:
+  - name: "ParentMarker1"
+    parents:
+    - name: "GrandMotherMarker"
+    - name: "GrandFatherMarker"
+  - name: "ParentMarker2"
+message: "Msg"
+thrown:
+  commonElementCount: 0
+  localizedMessage: "testIOEx"
+  message: "testIOEx"
+  name: "java.io.IOException"
+  cause:
+    commonElementCount: 27
+    localizedMessage: "testNPEx"
+    message: "testNPEx"
+    name: "java.lang.NullPointerException"
+    extendedStackTrace:
+    - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+      method: "createLogEvent"
+      file: "LogEventFixtures.java"
+      line: 52
+      exact: false
+      location: "test-classes/"
+      version: "?"
+  extendedStackTrace:
+  - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+    method: "createLogEvent"
+    file: "LogEventFixtures.java"
+    line: 55
+    exact: true
+    location: "test-classes/"
+    version: "?"
+  - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+    method: "testAllFeatures"
+    file: "YamlLayoutTest.java"
+    line: 109
+    exact: true
+    location: "test-classes/"
+    version: "?"
+  - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+    method: "testLocationOnCompactOffEventEolOffMdcOn"
+    file: "YamlLayoutTest.java"
+    line: 280
+    exact: true
+    location: "test-classes/"
+    version: "?"
+  - class: "sun.reflect.NativeMethodAccessorImpl"
+    method: "invoke0"
+    file: "NativeMethodAccessorImpl.java"
+    line: -2
+    exact: false
+    location: "?"
+    version: "1.7.0_79"
+  - class: "sun.reflect.NativeMethodAccessorImpl"
+    method: "invoke"
+    file: "NativeMethodAccessorImpl.java"
+    line: 57
+    exact: false
+    location: "?"
+    version: "1.7.0_79"
+  - class: "sun.reflect.DelegatingMethodAccessorImpl"
+    method: "invoke"
+    file: "DelegatingMethodAccessorImpl.java"
+    line: 43
+    exact: false
+    location: "?"
+    version: "1.7.0_79"
+  - class: "java.lang.reflect.Method"
+    method: "invoke"
+    file: "Method.java"
+    line: 606
+    exact: false
+    location: "?"
+    version: "1.7.0_79"
+  - class: "org.junit.runners.model.FrameworkMethod$1"
+    method: "runReflectiveCall"
+    file: "FrameworkMethod.java"
+    line: 50
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.internal.runners.model.ReflectiveCallable"
+    method: "run"
+    file: "ReflectiveCallable.java"
+    line: 12
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.model.FrameworkMethod"
+    method: "invokeExplosively"
+    file: "FrameworkMethod.java"
+    line: 47
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.internal.runners.statements.InvokeMethod"
+    method: "evaluate"
+    file: "InvokeMethod.java"
+    line: 17
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner"
+    method: "runLeaf"
+    file: "ParentRunner.java"
+    line: 325
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.BlockJUnit4ClassRunner"
+    method: "runChild"
+    file: "BlockJUnit4ClassRunner.java"
+    line: 78
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.BlockJUnit4ClassRunner"
+    method: "runChild"
+    file: "BlockJUnit4ClassRunner.java"
+    line: 57
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner$3"
+    method: "run"
+    file: "ParentRunner.java"
+    line: 290
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner$1"
+    method: "schedule"
+    file: "ParentRunner.java"
+    line: 71
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner"
+    method: "runChildren"
+    file: "ParentRunner.java"
+    line: 288
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner"
+    method: "access$000"
+    file: "ParentRunner.java"
+    line: 58
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner$2"
+    method: "evaluate"
+    file: "ParentRunner.java"
+    line: 268
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.internal.runners.statements.RunBefores"
+    method: "evaluate"
+    file: "RunBefores.java"
+    line: 26
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.internal.runners.statements.RunAfters"
+    method: "evaluate"
+    file: "RunAfters.java"
+    line: 27
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.junit.runners.ParentRunner"
+    method: "run"
+    file: "ParentRunner.java"
+    line: 363
+    exact: true
+    location: "junit-4.12.jar"
+    version: "4.12"
+  - class: "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference"
+    method: "run"
+    file: "JUnit4TestReference.java"
+    line: 86
+    exact: true
+    location: ".cp/"
+    version: "?"
+  - class: "org.eclipse.jdt.internal.junit.runner.TestExecution"
+    method: "run"
+    file: "TestExecution.java"
+    line: 38
+    exact: true
+    location: ".cp/"
+    version: "?"
+  - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+    method: "runTests"
+    file: "RemoteTestRunner.java"
+    line: 459
+    exact: true
+    location: ".cp/"
+    version: "?"
+  - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+    method: "runTests"
+    file: "RemoteTestRunner.java"
+    line: 675
+    exact: true
+    location: ".cp/"
+    version: "?"
+  - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+    method: "run"
+    file: "RemoteTestRunner.java"
+    line: 382
+    exact: true
+    location: ".cp/"
+    version: "?"
+  - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+    method: "main"
+    file: "RemoteTestRunner.java"
+    line: 192
+    exact: true
+    location: ".cp/"
+    version: "?"
+  suppressed:
+  - commonElementCount: 0
+    localizedMessage: "I am suppressed exception 1"
+    message: "I am suppressed exception 1"
+    name: "java.lang.IndexOutOfBoundsException"
+    extendedStackTrace:
+    - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+      method: "createLogEvent"
+      file: "LogEventFixtures.java"
+      line: 56
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testAllFeatures"
+      file: "YamlLayoutTest.java"
+      line: 109
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testLocationOnCompactOffEventEolOffMdcOn"
+      file: "YamlLayoutTest.java"
+      line: 280
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "sun.reflect.NativeMethodAccessorImpl"
+      method: "invoke0"
+      file: "NativeMethodAccessorImpl.java"
+      line: -2
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "sun.reflect.NativeMethodAccessorImpl"
+      method: "invoke"
+      file: "NativeMethodAccessorImpl.java"
+      line: 57
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "sun.reflect.DelegatingMethodAccessorImpl"
+      method: "invoke"
+      file: "DelegatingMethodAccessorImpl.java"
+      line: 43
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "java.lang.reflect.Method"
+      method: "invoke"
+      file: "Method.java"
+      line: 606
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "org.junit.runners.model.FrameworkMethod$1"
+      method: "runReflectiveCall"
+      file: "FrameworkMethod.java"
+      line: 50
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.model.ReflectiveCallable"
+      method: "run"
+      file: "ReflectiveCallable.java"
+      line: 12
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.model.FrameworkMethod"
+      method: "invokeExplosively"
+      file: "FrameworkMethod.java"
+      line: 47
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.statements.InvokeMethod"
+      method: "evaluate"
+      file: "InvokeMethod.java"
+      line: 17
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "runLeaf"
+      file: "ParentRunner.java"
+      line: 325
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.BlockJUnit4ClassRunner"
+      method: "runChild"
+      file: "BlockJUnit4ClassRunner.java"
+      line: 78
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.BlockJUnit4ClassRunner"
+      method: "runChild"
+      file: "BlockJUnit4ClassRunner.java"
+      line: 57
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner$3"
+      method: "run"
+      file: "ParentRunner.java"
+      line: 290
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner$1"
+      method: "schedule"
+      file: "ParentRunner.java"
+      line: 71
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "runChildren"
+      file: "ParentRunner.java"
+      line: 288
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "access$000"
+      file: "ParentRunner.java"
+      line: 58
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner$2"
+      method: "evaluate"
+      file: "ParentRunner.java"
+      line: 268
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.statements.RunBefores"
+      method: "evaluate"
+      file: "RunBefores.java"
+      line: 26
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.statements.RunAfters"
+      method: "evaluate"
+      file: "RunAfters.java"
+      line: 27
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "run"
+      file: "ParentRunner.java"
+      line: 363
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference"
+      method: "run"
+      file: "JUnit4TestReference.java"
+      line: 86
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.TestExecution"
+      method: "run"
+      file: "TestExecution.java"
+      line: 38
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "runTests"
+      file: "RemoteTestRunner.java"
+      line: 459
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "runTests"
+      file: "RemoteTestRunner.java"
+      line: 675
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "run"
+      file: "RemoteTestRunner.java"
+      line: 382
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "main"
+      file: "RemoteTestRunner.java"
+      line: 192
+      exact: true
+      location: ".cp/"
+      version: "?"
+  - commonElementCount: 0
+    localizedMessage: "I am suppressed exception 2"
+    message: "I am suppressed exception 2"
+    name: "java.lang.IndexOutOfBoundsException"
+    extendedStackTrace:
+    - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+      method: "createLogEvent"
+      file: "LogEventFixtures.java"
+      line: 57
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testAllFeatures"
+      file: "YamlLayoutTest.java"
+      line: 109
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testLocationOnCompactOffEventEolOffMdcOn"
+      file: "YamlLayoutTest.java"
+      line: 280
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "sun.reflect.NativeMethodAccessorImpl"
+      method: "invoke0"
+      file: "NativeMethodAccessorImpl.java"
+      line: -2
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "sun.reflect.NativeMethodAccessorImpl"
+      method: "invoke"
+      file: "NativeMethodAccessorImpl.java"
+      line: 57
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "sun.reflect.DelegatingMethodAccessorImpl"
+      method: "invoke"
+      file: "DelegatingMethodAccessorImpl.java"
+      line: 43
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "java.lang.reflect.Method"
+      method: "invoke"
+      file: "Method.java"
+      line: 606
+      exact: false
+      location: "?"
+      version: "1.7.0_79"
+    - class: "org.junit.runners.model.FrameworkMethod$1"
+      method: "runReflectiveCall"
+      file: "FrameworkMethod.java"
+      line: 50
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.model.ReflectiveCallable"
+      method: "run"
+      file: "ReflectiveCallable.java"
+      line: 12
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.model.FrameworkMethod"
+      method: "invokeExplosively"
+      file: "FrameworkMethod.java"
+      line: 47
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.statements.InvokeMethod"
+      method: "evaluate"
+      file: "InvokeMethod.java"
+      line: 17
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "runLeaf"
+      file: "ParentRunner.java"
+      line: 325
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.BlockJUnit4ClassRunner"
+      method: "runChild"
+      file: "BlockJUnit4ClassRunner.java"
+      line: 78
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.BlockJUnit4ClassRunner"
+      method: "runChild"
+      file: "BlockJUnit4ClassRunner.java"
+      line: 57
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner$3"
+      method: "run"
+      file: "ParentRunner.java"
+      line: 290
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner$1"
+      method: "schedule"
+      file: "ParentRunner.java"
+      line: 71
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "runChildren"
+      file: "ParentRunner.java"
+      line: 288
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "access$000"
+      file: "ParentRunner.java"
+      line: 58
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner$2"
+      method: "evaluate"
+      file: "ParentRunner.java"
+      line: 268
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.statements.RunBefores"
+      method: "evaluate"
+      file: "RunBefores.java"
+      line: 26
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.internal.runners.statements.RunAfters"
+      method: "evaluate"
+      file: "RunAfters.java"
+      line: 27
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.junit.runners.ParentRunner"
+      method: "run"
+      file: "ParentRunner.java"
+      line: 363
+      exact: true
+      location: "junit-4.12.jar"
+      version: "4.12"
+    - class: "org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference"
+      method: "run"
+      file: "JUnit4TestReference.java"
+      line: 86
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.TestExecution"
+      method: "run"
+      file: "TestExecution.java"
+      line: 38
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "runTests"
+      file: "RemoteTestRunner.java"
+      line: 459
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "runTests"
+      file: "RemoteTestRunner.java"
+      line: 675
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "run"
+      file: "RemoteTestRunner.java"
+      line: 382
+      exact: true
+      location: ".cp/"
+      version: "?"
+    - class: "org.eclipse.jdt.internal.junit.runner.RemoteTestRunner"
+      method: "main"
+      file: "RemoteTestRunner.java"
+      line: 192
+      exact: true
+      location: ".cp/"
+      version: "?"
+contextStack:
+- "stack_msg1"
+- "stack_msg2"
+endOfBatch: false
+loggerFqcn: "f.q.c.n"
+contextMap:
+- key: "MDC.B"
+  value: "B_Value"
+- key: "MDC.A"
+  value: "A_Value"
+threadId: 1
+threadPriority: 5
+source:
+  class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+  method: "createLogEvent"
+  file: "LogEventFixtures.java"
+  line: 53</pre>
  * <p>
  * This approach enforces the independence of the YamlLayout and the appender where you embed it.
  * </p>
@@ -61,19 +698,13 @@ import org.apache.logging.log4j.core.config.plugins.PluginFactory;
  * Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
  * events containing non ASCII characters could result in corrupted log files.
  * </p>
- * <h3>Pretty vs. compact YAML</h3>
- * <p>
- * By default, the YAML layout is not compact (a.k.a. "pretty") with {@code compact="false"}, which means the appender
- * uses end-of-line characters and indents lines to format the text. If {@code compact="true"}, then no end-of-line or
- * indentation is used. Message content may contain, of course, escaped end-of-lines.
- * </p>
  */
-@Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
+@Plugin(name = "YamlLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
 public final class YamlLayout extends AbstractJacksonLayout {
 
-    private static final String DEFAULT_FOOTER = ""; // TODO maybe
+    private static final String DEFAULT_FOOTER = Strings.EMPTY;
 
-    private static final String DEFAULT_HEADER = ""; // TODO maybe
+    private static final String DEFAULT_HEADER = Strings.EMPTY;
 
     static final String CONTENT_TYPE = "application/yaml";
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ffbd8c9b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
index 6634fde..d8355a3 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/JsonCompleteFileAppenderTest.java
@@ -30,7 +30,7 @@ import org.junit.rules.RuleChain;
 import static org.junit.Assert.*;
 
 /**
- * Tests a "complete" XML file a.k.a. a well-formed XML file.
+ * Tests a "complete" JSON file.
  */
 public class JsonCompleteFileAppenderTest {
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ffbd8c9b/src/site/site.xml
----------------------------------------------------------------------
diff --git a/src/site/site.xml b/src/site/site.xml
index 71819c2..b7f7a35 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -140,6 +140,7 @@
         <item name="Serialized" href="/manual/layouts.html#SerializedLayout"/>
         <item name="Syslog" href="/manual/layouts.html#SyslogLayout"/>
         <item name="XML" href="/manual/layouts.html#XMLLayout"/>
+        <item name="YAML" href="/manual/layouts.html#YamlLayout"/>
         <item name="Location Information" href="/manual/layouts.html#LocationInformation"/>
       </item>
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/ffbd8c9b/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 31ac6bd..ae4c1a0 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -1811,6 +1811,157 @@ at org.apache.logging.log4j.core.pattern.ExtendedThrowableTest.testException(Ext
           of course, end-of-lines.
           </p>
         </subsection>
+        <a name="YamlLayout"/>
+        <subsection name="YamlLayout">
+          <!-- From Javadoc of org.apache.logging.log4j.core.layout.YamlLayout -->
+          <p>
+            Appends a series of YAML events as strings serialized as bytes.
+          </p>
+          <p>
+            A YAML log event follows this pattern:
+          </p>
+          <pre>---
+timeMillis: 1
+thread: "MyThreadName"
+level: "DEBUG"
+loggerName: "a.B"
+marker:
+  name: "Marker1"
+  parents:
+  - name: "ParentMarker1"
+    parents:
+    - name: "GrandMotherMarker"
+    - name: "GrandFatherMarker"
+  - name: "ParentMarker2"
+message: "Msg"
+thrown:
+  commonElementCount: 0
+  localizedMessage: "testIOEx"
+  message: "testIOEx"
+  name: "java.io.IOException"
+  cause:
+    commonElementCount: 27
+    localizedMessage: "testNPEx"
+    message: "testNPEx"
+    name: "java.lang.NullPointerException"
+    extendedStackTrace:
+    - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+      method: "createLogEvent"
+      file: "LogEventFixtures.java"
+      line: 52
+      exact: false
+      location: "test-classes/"
+      version: "?"
+  extendedStackTrace:
+  - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+    method: "createLogEvent"
+    file: "LogEventFixtures.java"
+    line: 55
+    exact: true
+    location: "test-classes/"
+    version: "?"
+  - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+    method: "testAllFeatures"
+    file: "YamlLayoutTest.java"
+    line: 109
+    exact: true
+    location: "test-classes/"
+    version: "?"
+  - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+    method: "testLocationOnCompactOffEventEolOffMdcOn"
+    file: "YamlLayoutTest.java"
+    line: 280
+    exact: true
+    location: "test-classes/"
+    version: "?"
+
+...
+
+  suppressed:
+  - commonElementCount: 0
+    localizedMessage: "I am suppressed exception 1"
+    message: "I am suppressed exception 1"
+    name: "java.lang.IndexOutOfBoundsException"
+    extendedStackTrace:
+    - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+      method: "createLogEvent"
+      file: "LogEventFixtures.java"
+      line: 56
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testAllFeatures"
+      file: "YamlLayoutTest.java"
+      line: 109
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testLocationOnCompactOffEventEolOffMdcOn"
+      file: "YamlLayoutTest.java"
+      line: 280
+      exact: true
+      location: "test-classes/"
+      version: "?"
+
+...
+
+  - commonElementCount: 0
+    localizedMessage: "I am suppressed exception 2"
+    message: "I am suppressed exception 2"
+    name: "java.lang.IndexOutOfBoundsException"
+    extendedStackTrace:
+    - class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+      method: "createLogEvent"
+      file: "LogEventFixtures.java"
+      line: 57
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testAllFeatures"
+      file: "YamlLayoutTest.java"
+      line: 109
+      exact: true
+      location: "test-classes/"
+      version: "?"
+    - class: "org.apache.logging.log4j.core.layout.YamlLayoutTest"
+      method: "testLocationOnCompactOffEventEolOffMdcOn"
+      file: "YamlLayoutTest.java"
+      line: 280
+      exact: true
+      location: "test-classes/"
+      version: "?"
+
+...
+
+contextStack:
+- "stack_msg1"
+- "stack_msg2"
+endOfBatch: false
+loggerFqcn: "f.q.c.n"
+contextMap:
+- key: "MDC.B"
+  value: "B_Value"
+- key: "MDC.A"
+  value: "A_Value"
+threadId: 1
+threadPriority: 5
+source:
+  class: "org.apache.logging.log4j.core.layout.LogEventFixtures"
+  method: "createLogEvent"
+  file: "LogEventFixtures.java"
+  line: 53</pre>
+        <p>
+          This approach enforces the independence of the YamlLayout and the appender where you embed it.
+        </p>
+        <h4>Encoding</h4>
+        <p>
+          Appenders using this layout should have their {@code charset} set to {@code UTF-8} or {@code UTF-16}, otherwise
+          events containing non ASCII characters could result in corrupted log files.
+        </p>
+        </subsection>
         <a name="LocationInformation"/>
         <subsection name="Location Information">
         <p>


[3/4] logging-log4j2 git commit: Fix appender name.

Posted by gg...@apache.org.
Fix appender name.

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

Branch: refs/heads/master
Commit: 51142337af823fd49dcfee17527cefd424e5fe6c
Parents: 98cc7d2
Author: ggregory <gg...@apache.org>
Authored: Sun Apr 17 15:46:45 2016 -0700
Committer: ggregory <gg...@apache.org>
Committed: Sun Apr 17 15:46:45 2016 -0700

----------------------------------------------------------------------
 log4j-core/src/test/resources/JsonCompleteFileAppenderTest.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/51142337/log4j-core/src/test/resources/JsonCompleteFileAppenderTest.xml
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/resources/JsonCompleteFileAppenderTest.xml b/log4j-core/src/test/resources/JsonCompleteFileAppenderTest.xml
index 0f83ae5..7298437 100644
--- a/log4j-core/src/test/resources/JsonCompleteFileAppenderTest.xml
+++ b/log4j-core/src/test/resources/JsonCompleteFileAppenderTest.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Configuration status="OFF">
   <Appenders>
-    <File name="XmlFile" fileName="target/JsonCompleteFileAppenderTest.log" immediateFlush="true" append="false">
+    <File name="JsonFile" fileName="target/JsonCompleteFileAppenderTest.log" immediateFlush="true" append="false">
       <JSONLayout complete="true" charset="UTF-8"/>
     </File>
   </Appenders>
 
   <Loggers>
     <Root level="info" includeLocation="false">
-      <AppenderRef ref="XmlFile"/>
+      <AppenderRef ref="JsonFile"/>
     </Root>
   </Loggers>
 </Configuration>


[2/4] logging-log4j2 git commit: Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/logging-log4j2.git

Posted by gg...@apache.org.
Merge branch 'master' of https://git-wip-us.apache.org/repos/asf/logging-log4j2.git

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

Branch: refs/heads/master
Commit: 98cc7d27c6d49da3f81ae6ff8cee2f4b0a4009e5
Parents: 80a4398 3c37ca3
Author: ggregory <gg...@apache.org>
Authored: Sun Apr 17 15:27:42 2016 -0700
Committer: ggregory <gg...@apache.org>
Committed: Sun Apr 17 15:27:42 2016 -0700

----------------------------------------------------------------------
 .../ParameterizedNoReferenceMessageFactory.java |  39 ++++-
 log4j-core/pom.xml                              |   5 +
 .../log4j/core/appender/AsyncAppender.java      |  28 +--
 .../log4j/core/appender/FileManager.java        |   3 +-
 .../core/appender/OutputStreamManager.java      |   7 +-
 .../appender/rolling/RollingFileManager.java    |   4 +-
 .../log4j/core/async/AsyncLoggerConfig.java     |   1 +
 .../core/async/AsyncLoggerConfigDelegate.java   |  10 ++
 .../core/async/AsyncLoggerConfigDisruptor.java  |  66 +++++++-
 .../logging/log4j/core/async/EventRoute.java    |   9 +-
 .../log4j/core/async/RingBufferLogEvent.java    |  15 +-
 .../core/async/ThreadNameCachingStrategy.java   |   4 +-
 .../logging/log4j/core/config/LoggerConfig.java |   5 +-
 .../log4j/core/impl/MutableLogEvent.java        |  46 +++--
 .../core/impl/ReusableLogEventFactory.java      |  34 ++--
 .../log4j/core/jackson/Initializers.java        |   2 +-
 .../core/layout/AbstractJacksonLayout.java      |  17 +-
 .../core/layout/ByteBufferDestination.java      |   8 +-
 .../log4j/core/layout/JacksonFactory.java       |   2 +-
 .../layout/LockingStringBuilderEncoder.java     |   3 +-
 .../log4j/core/layout/StringBuilderEncoder.java |   3 +-
 .../log4j/core/layout/TextEncoderHelper.java    |   1 -
 .../logging/log4j/core/net/SmtpManager.java     |   5 +-
 .../ExtendedThrowablePatternConverter.java      |   5 +-
 .../pattern/RootThrowablePatternConverter.java  |   5 +-
 .../logging/log4j/core/util/Constants.java      |  45 ++++-
 .../core/GcFreeAsynchronousLoggingTest.java     |  41 +++++
 .../logging/log4j/core/GcFreeLoggingTest.java   | 167 ------------------
 .../log4j/core/GcFreeLoggingTestUtil.java       | 169 +++++++++++++++++++
 .../core/GcFreeMixedSyncAyncLoggingTest.java    |  58 +++++++
 .../core/GcFreeSynchronousLoggingTest.java      |  58 +++++++
 .../log4j/core/async/perftest/IdleStrategy.java |  43 +++++
 .../core/async/perftest/NoOpIdleStrategy.java   |  34 ++++
 .../core/async/perftest/SimpleLatencyTest.java  | 118 +++++++++----
 .../log4j/core/impl/MutableLogEventTest.java    |  86 ++++++++++
 .../log4j/test/appender/ListAppender.java       |   9 +-
 .../resources/gcFreeMixedSyncAsyncLogging.xml   |  71 ++++++++
 pom.xml                                         |   5 +
 src/changes/changes.xml                         |   3 +
 39 files changed, 926 insertions(+), 308 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/98cc7d27/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JacksonFactory.java
----------------------------------------------------------------------