You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by mi...@apache.org on 2016/01/12 17:50:52 UTC

[44/50] logging-log4j2 git commit: [LOG4J2-1244] Make header and footer values customizable in JSONLayout. [LOG4J2-1245] Make CSV Layout header and footers accept patterns.

[LOG4J2-1244] Make header and footer values customizable in JSONLayout. 
[LOG4J2-1245] Make CSV Layout header and footers accept patterns. 


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

Branch: refs/heads/LOG4J-1181
Commit: 75d33d96ac00356014cf11f8ad9e8c6ead4db37a
Parents: 5b1404b
Author: ggregory <gg...@apache.org>
Authored: Tue Jan 5 18:57:38 2016 -0800
Committer: ggregory <gg...@apache.org>
Committed: Tue Jan 5 18:57:38 2016 -0800

----------------------------------------------------------------------
 .../log4j/core/layout/AbstractCsvLayout.java    |   9 +-
 .../core/layout/AbstractJacksonLayout.java      |  11 +-
 .../log4j/core/layout/AbstractLayout.java       |  45 +++++-
 .../log4j/core/layout/AbstractStringLayout.java | 158 ++++++++++++++-----
 .../log4j/core/layout/CsvLogEventLayout.java    |  15 +-
 .../log4j/core/layout/CsvParameterLayout.java   |  15 +-
 .../logging/log4j/core/layout/JsonLayout.java   |  51 ++++--
 .../log4j/core/layout/PatternLayout.java        |  52 +-----
 .../log4j/core/layout/SerializedLayout.java     |   2 +-
 .../logging/log4j/core/layout/XmlLayout.java    |   2 +-
 .../logging/log4j/core/net/SmtpManager.java     |   4 +-
 .../core/layout/CsvLogEventLayoutTest.java      |  44 +++++-
 .../core/layout/CsvParameterLayoutTest.java     |   4 +-
 .../log4j/core/layout/JsonLayoutTest.java       |  17 +-
 .../net/server/AbstractSocketServerTest.java    |   2 +-
 src/changes/changes.xml                         |   6 +
 16 files changed, 295 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractCsvLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractCsvLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractCsvLayout.java
index ae55447..c5b0e90 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractCsvLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractCsvLayout.java
@@ -20,7 +20,7 @@ import java.nio.charset.Charset;
 
 import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.csv.QuoteMode;
-import org.apache.logging.log4j.core.util.StringEncoder;
+import org.apache.logging.log4j.core.config.Configuration;
 
 /**
  * A superclass for Comma-Separated Value (CSV) layouts.
@@ -38,9 +38,10 @@ public abstract class AbstractCsvLayout extends AbstractStringLayout {
 
     private final CSVFormat format;
 
-    protected AbstractCsvLayout(final Charset charset, final CSVFormat csvFormat, final String header,
-            final String footer) {
-        super(charset, StringEncoder.toBytes(header, charset), StringEncoder.toBytes(footer, charset));
+    protected AbstractCsvLayout(final Configuration config, final Charset charset, final CSVFormat csvFormat,
+            final String header, final String footer) {
+        super(config, charset, PatternLayout.createSerializer(config, null, header, null, null, false, false),
+                PatternLayout.createSerializer(config, null, footer, null, null, false, false));
         this.format = csvFormat;
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
index 3b122e1..ced02e2 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractJacksonLayout.java
@@ -21,6 +21,7 @@ import java.io.Writer;
 import java.nio.charset.Charset;
 
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.core.util.StringBuilderWriter;
 import org.apache.logging.log4j.util.Strings;
 
@@ -39,8 +40,10 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout {
     protected final boolean compact;
     protected final boolean complete;
 
-    protected AbstractJacksonLayout(final ObjectWriter objectWriter, final Charset charset, final boolean compact, final boolean complete, final boolean eventEol) {
-        super(charset);
+    protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset,
+            final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer,
+            final Serializer footerSerializer) {
+        super(config, charset, headerSerializer, footerSerializer);
         this.objectWriter = objectWriter;
         this.compact = compact;
         this.complete = complete;
@@ -55,7 +58,7 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout {
      */
     @Override
     public String toSerializable(final LogEvent event) {
-        StringBuilderWriter writer = new StringBuilderWriter();        
+        final StringBuilderWriter writer = new StringBuilderWriter();        
         try {
             toSerializable(event, writer);
             return writer.toString();
@@ -66,7 +69,7 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout {
         }
     }
 
-    public void toSerializable(final LogEvent event, Writer writer)
+    public void toSerializable(final LogEvent event, final Writer writer)
             throws JsonGenerationException, JsonMappingException, IOException {
         objectWriter.writeValue(writer, event);
         writer.write(eol);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java
index 9c5166e..fae6349 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractLayout.java
@@ -22,13 +22,14 @@ import java.util.Map;
 
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.config.Configuration;
 import org.apache.logging.log4j.status.StatusLogger;
 
 /**
  * Abstract base class for Layouts.
  * 
  * @param <T>
- *        The Class that the Layout will format the LogEvent into.
+ *            The Class that the Layout will format the LogEvent into.
  */
 public abstract class AbstractLayout<T extends Serializable> implements Layout<T>, Serializable {
 
@@ -40,9 +41,14 @@ public abstract class AbstractLayout<T extends Serializable> implements Layout<T
     private static final long serialVersionUID = 1L;
 
     /**
-     * The header to include when the stream is opened. May be null.
+     * The current Configuration.
      */
-    protected final byte[] header;
+    protected final Configuration configuration;
+
+    /**
+     * The number of events successfully processed by this layout.
+     */
+    protected long eventCount;
 
     /**
      * The footer to add when the stream is closed. May be null.
@@ -50,24 +56,47 @@ public abstract class AbstractLayout<T extends Serializable> implements Layout<T
     protected final byte[] footer;
 
     /**
-     * The count of events successfully processed by this layout.
+     * The header to include when the stream is opened. May be null.
      */
-    protected long eventCount;
+    protected final byte[] header;
 
     /**
      * Constructs a layout with an optional header and footer.
      * 
+     * @param configuration
+     *            The configuration
      * @param header
-     *        The header to include when the stream is opened. May be null.
+     *            The header to include when the stream is opened. May be null.
      * @param footer
-     *        The footer to add when the stream is closed. May be null.
+     *            The footer to add when the stream is closed. May be null.
+     * @deprecated Use {@link #AbstractLayout(Configuration, byte[], byte[])}
      */
+    @Deprecated
     public AbstractLayout(final byte[] header, final byte[] footer) {
+        this(null, header, footer);
+    }
+
+    /**
+     * Constructs a layout with an optional header and footer.
+     * 
+     * @param configuration
+     *            The configuration
+     * @param header
+     *            The header to include when the stream is opened. May be null.
+     * @param footer
+     *            The footer to add when the stream is closed. May be null.
+     */
+    public AbstractLayout(final Configuration configuration, final byte[] header, final byte[] footer) {
         super();
+        this.configuration = configuration;
         this.header = header;
         this.footer = footer;
     }
 
+    public Configuration getConfiguration() {
+        return configuration;
+    }
+
     @Override
     public Map<String, String> getContentFormat() {
         return new HashMap<>();
@@ -92,7 +121,7 @@ public abstract class AbstractLayout<T extends Serializable> implements Layout<T
     public byte[] getHeader() {
         return header;
     }
-    
+
     protected void markEvent() {
         eventCount++;
     }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
index 96a80a5..91e21ef 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/AbstractStringLayout.java
@@ -25,7 +25,10 @@ import java.nio.charset.StandardCharsets;
 
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.StringLayout;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.LoggerConfig;
 import org.apache.logging.log4j.core.util.StringEncoder;
+import org.apache.logging.log4j.util.Strings;
 
 /**
  * Abstract base class for Layouts that result in a String.
@@ -39,41 +42,19 @@ import org.apache.logging.log4j.core.util.StringEncoder;
  */
 public abstract class AbstractStringLayout extends AbstractLayout<String> implements StringLayout {
 
+    public interface Serializer {
+        
+        String toSerializable(final LogEvent event);        
+    }
+
     /**
      * Default length for new StringBuilder instances: {@value} .
      */
     protected static final int DEFAULT_STRING_BUILDER_SIZE = 1024;
 
-    private final static ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();
-
     private static final long serialVersionUID = 1L;
 
-    /**
-     * The charset for the formatted message.
-     */
-    // LOG4J2-1099: charset cannot be final due to serialization needs, so we serialize as charset name instead
-    private transient Charset charset;
-    private final String charsetName;
-    private final boolean useCustomEncoding;
-
-    protected AbstractStringLayout(final Charset charset) {
-        this(charset, null, null);
-    }
-
-    /**
-     * Builds a new layout.
-     * @param charset the charset used to encode the header bytes, footer bytes and anything else that needs to be 
-     *      converted from strings to bytes.
-     * @param header the header bytes
-     * @param footer the footer bytes
-     */
-    protected AbstractStringLayout(final Charset charset, final byte[] header, final byte[] footer) {
-        super(header, footer);
-        this.charset = charset == null ? StandardCharsets.UTF_8 : charset;
-        this.charsetName = this.charset.name();
-        useCustomEncoding = isPreJava8()
-                && (StandardCharsets.ISO_8859_1.equals(charset) || StandardCharsets.US_ASCII.equals(charset));
-    }
+    private final static ThreadLocal<StringBuilder> threadLocal = new ThreadLocal<>();
 
     /**
      * Returns a {@code StringBuilder} that this Layout implementation can use to write the formatted log event to.
@@ -89,28 +70,68 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
         result.setLength(0);
         return result;
     }
-
     // LOG4J2-1151: If the built-in JDK 8 encoders are available we should use them.
     private static boolean isPreJava8() {
         final String version = System.getProperty("java.version");
         final String[] parts = version.split("\\.");
         try {
-            int major = Integer.parseInt(parts[1]);
+            final int major = Integer.parseInt(parts[1]);
             return major < 8;
-        } catch (Exception ex) {
+        } catch (final Exception ex) {
             return true;
         }
     }
+    /**
+     * The charset for the formatted message.
+     */
+    // LOG4J2-1099: charset cannot be final due to serialization needs, so we serialize as charset name instead
+    private transient Charset charset;
 
-    private void writeObject(final ObjectOutputStream out) throws IOException {
-        out.defaultWriteObject();
-        out.writeUTF(charset.name());
+    private final String charsetName;
+
+    private final Serializer footerSerializer;
+
+    private final Serializer headerSerializer;
+
+    private final boolean useCustomEncoding;
+
+    protected AbstractStringLayout(final Charset charset) {
+        this(charset, (byte[]) null, (byte[]) null);
+    }
+    
+    /**
+     * Builds a new layout.
+     * @param charset the charset used to encode the header bytes, footer bytes and anything else that needs to be 
+     *      converted from strings to bytes.
+     * @param header the header bytes
+     * @param footer the footer bytes
+     */
+    protected AbstractStringLayout(final Charset charset, final byte[] header, final byte[] footer) {
+        super(null, header, footer);
+        this.headerSerializer = null;
+        this.footerSerializer = null;
+        this.charset = charset == null ? StandardCharsets.UTF_8 : charset;
+        this.charsetName = this.charset.name();
+        useCustomEncoding = isPreJava8()
+                && (StandardCharsets.ISO_8859_1.equals(charset) || StandardCharsets.US_ASCII.equals(charset));
     }
 
-    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
-        in.defaultReadObject();
-        final String csName = in.readUTF();
-        charset = Charset.forName(csName);
+    /**
+     * Builds a new layout.
+     * @param Configuration config the configuration
+     * @param charset the charset used to encode the header bytes, footer bytes and anything else that needs to be 
+     *      converted from strings to bytes.
+     * @param header the header bytes serializer
+     * @param footer the footer bytes serializer
+     */
+    protected AbstractStringLayout(final Configuration config, final Charset charset, final Serializer headerSerializer, final Serializer footerSerializer) {
+        super(config, null, null);
+        this.headerSerializer = headerSerializer;
+        this.footerSerializer = footerSerializer;
+        this.charset = charset == null ? StandardCharsets.UTF_8 : charset;
+        this.charsetName = this.charset.name();
+        useCustomEncoding = isPreJava8()
+                && (StandardCharsets.ISO_8859_1.equals(charset) || StandardCharsets.US_ASCII.equals(charset));
     }
 
     protected byte[] getBytes(final String s) {
@@ -119,7 +140,7 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
         }
         try { // LOG4J2-935: String.getBytes(String) gives better performance
             return s.getBytes(charsetName);
-        } catch (UnsupportedEncodingException e) {
+        } catch (final UnsupportedEncodingException e) {
             return s.getBytes(charset);
         }
     }
@@ -129,6 +150,7 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
         return charset;
     }
 
+
     /**
      * @return The default content type for Strings.
      */
@@ -138,6 +160,59 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
     }
 
     /**
+     * Returns the footer, if one is available.
+     * 
+     * @return A byte array containing the footer.
+     */
+    @Override
+    public byte[] getFooter() {
+        return serializeToBytes(footerSerializer, super.getFooter());
+    }
+
+    public Serializer getFooterSerializer() {
+        return footerSerializer;
+    }
+
+    /**
+     * Returns the header, if one is available.
+     * 
+     * @return A byte array containing the header.
+     */
+    @Override
+    public byte[] getHeader() {
+        return serializeToBytes(headerSerializer, super.getHeader());
+    }
+
+    public Serializer getHeaderSerializer() {
+        return headerSerializer;
+    }
+
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        final String csName = in.readUTF();
+        charset = Charset.forName(csName);
+    }
+
+    protected byte[] serializeToBytes(final Serializer serializer, byte[] defaultValue) {
+        final String serializable = serializeToString(serializer);
+        if (serializer == null) {
+            return defaultValue;
+        }
+        return StringEncoder.toBytes(serializable, getCharset());
+    }
+
+    protected String serializeToString(final Serializer serializer) {
+        if (serializer == null) {
+            return null;
+        }
+        final LoggerConfig rootLogger = getConfiguration().getRootLogger();
+        // Using "" for the FQCN, does it matter?
+        final LogEvent logEvent = rootLogger.getLogEventFactory().createEvent(rootLogger.getName(), null, Strings.EMPTY,
+                rootLogger.getLevel(), null, null, null);
+        return serializer.toSerializable(logEvent);
+    }
+    
+    /**
      * Formats the Log Event as a byte array.
      *
      * @param event The Log Event.
@@ -147,5 +222,10 @@ public abstract class AbstractStringLayout extends AbstractLayout<String> implem
     public byte[] toByteArray(final LogEvent event) {
         return getBytes(toSerializable(event));
     }
+    
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        out.writeUTF(charset.name());
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
index 9b737fe..dd751f9 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvLogEventLayout.java
@@ -24,9 +24,11 @@ import org.apache.commons.csv.CSVPrinter;
 import org.apache.commons.csv.QuoteMode;
 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.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;
 import org.apache.logging.log4j.status.StatusLogger;
 
@@ -43,16 +45,17 @@ public class CsvLogEventLayout extends AbstractCsvLayout {
     private static final long serialVersionUID = 1L;
     
     public static CsvLogEventLayout createDefaultLayout() {
-        return new CsvLogEventLayout(Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null);
+        return new CsvLogEventLayout(null, Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null);
     }
 
     public static CsvLogEventLayout createLayout(final CSVFormat format) {
-        return new CsvLogEventLayout(Charset.forName(DEFAULT_CHARSET), format, null, null);
+        return new CsvLogEventLayout(null, Charset.forName(DEFAULT_CHARSET), format, null, null);
     }
 
     @PluginFactory
     public static CsvLogEventLayout createLayout(
             // @formatter:off
+            @PluginConfiguration final Configuration config,
             @PluginAttribute(value = "format", defaultString = DEFAULT_FORMAT) final String format,
             @PluginAttribute("delimiter") final Character delimiter,
             @PluginAttribute("escape") final Character escape,
@@ -61,17 +64,17 @@ public class CsvLogEventLayout extends AbstractCsvLayout {
             @PluginAttribute("nullString") final String nullString,
             @PluginAttribute("recordSeparator") final String recordSeparator,
             @PluginAttribute(value = "charset", defaultString = DEFAULT_CHARSET) final Charset charset,
-            @PluginAttribute("header") final String header,
+            @PluginAttribute("header") final String header, 
             @PluginAttribute("footer") final String footer)
             // @formatter:on
     {
 
         final CSVFormat csvFormat = createFormat(format, delimiter, escape, quote, quoteMode, nullString, recordSeparator);
-        return new CsvLogEventLayout(charset, csvFormat, header, footer);
+        return new CsvLogEventLayout(config, charset, csvFormat, header, footer);
     }
    
-    protected CsvLogEventLayout(final Charset charset, final CSVFormat csvFormat, final String header, final String footer) {
-        super(charset, csvFormat, header, footer);
+    protected CsvLogEventLayout(final Configuration config, final Charset charset, final CSVFormat csvFormat, final String header, final String footer) {
+        super(config, charset, csvFormat, header, footer);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java
index fb43964..324a08a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/CsvParameterLayout.java
@@ -24,9 +24,11 @@ import org.apache.commons.csv.CSVPrinter;
 import org.apache.commons.csv.QuoteMode;
 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.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;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.status.StatusLogger;
@@ -52,16 +54,17 @@ public class CsvParameterLayout extends AbstractCsvLayout {
     private static final long serialVersionUID = 1L;
     
     public static AbstractCsvLayout createDefaultLayout() {
-        return new CsvParameterLayout(Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null);
+        return new CsvParameterLayout(null, Charset.forName(DEFAULT_CHARSET), CSVFormat.valueOf(DEFAULT_FORMAT), null, null);
     }
 
     public static AbstractCsvLayout createLayout(final CSVFormat format) {
-        return new CsvParameterLayout(Charset.forName(DEFAULT_CHARSET), format, null, null);
+        return new CsvParameterLayout(null, Charset.forName(DEFAULT_CHARSET), format, null, null);
     }
 
     @PluginFactory
     public static AbstractCsvLayout createLayout(
             // @formatter:off
+            @PluginConfiguration final Configuration config,
             @PluginAttribute(value = "format", defaultString = DEFAULT_FORMAT) final String format,
             @PluginAttribute("delimiter") final Character delimiter,
             @PluginAttribute("escape") final Character escape,
@@ -70,17 +73,17 @@ public class CsvParameterLayout extends AbstractCsvLayout {
             @PluginAttribute("nullString") final String nullString,
             @PluginAttribute("recordSeparator") final String recordSeparator,
             @PluginAttribute(value = "charset", defaultString = DEFAULT_CHARSET) final Charset charset,
-            @PluginAttribute("header") final String header,
+            @PluginAttribute("header") final String header, 
             @PluginAttribute("footer") final String footer)
             // @formatter:on
     {
 
         final CSVFormat csvFormat = createFormat(format, delimiter, escape, quote, quoteMode, nullString, recordSeparator);
-        return new CsvParameterLayout(charset, csvFormat, header, footer);
+        return new CsvParameterLayout(config, charset, csvFormat, header, footer);
     }
 
-    public CsvParameterLayout(final Charset charset, final CSVFormat csvFormat, final String header, final String footer) {
-        super(charset, csvFormat, header, footer);
+    public CsvParameterLayout(final Configuration config, final Charset charset, final CSVFormat csvFormat, final String header, final String footer) {
+        super(config, charset, csvFormat, header, footer);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
index e403731..fe1a3b4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/JsonLayout.java
@@ -25,9 +25,12 @@ 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;
 
 /**
@@ -798,14 +801,21 @@ import org.apache.logging.log4j.core.config.plugins.PluginFactory;
 @Plugin(name = "JsonLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
 public final class JsonLayout extends AbstractJacksonLayout {
 
+    private static final String DEFAULT_FOOTER = "]";
+
+    private static final String DEFAULT_HEADER = "[";
+
     static final String CONTENT_TYPE = "application/json";
 
     private static final long serialVersionUID = 1L;
 
-    protected JsonLayout(final boolean locationInfo, final boolean properties, final boolean complete,
-            final boolean compact, final boolean eventEol, final Charset charset) {
-        super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete,
-                eventEol);
+    protected JsonLayout(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.JSON().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));
     }
 
     /**
@@ -819,7 +829,10 @@ public final class JsonLayout extends AbstractJacksonLayout {
             return null;
         }
         final StringBuilder buf = new StringBuilder();
-        buf.append('[');
+        final String str = serializeToString(getHeaderSerializer());
+        if (str != null) {
+            buf.append(str);
+        }
         buf.append(this.eol);
         return getBytes(buf.toString());
     }
@@ -834,7 +847,14 @@ public final class JsonLayout extends AbstractJacksonLayout {
         if (!this.complete) {
             return null;
         }
-        return getBytes(this.eol + ']' + this.eol);
+        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
@@ -854,7 +874,8 @@ public final class JsonLayout extends AbstractJacksonLayout {
 
     /**
      * Creates a JSON Layout.
-     *
+     * @param config 
+     *           The plugin configuration.
      * @param locationInfo
      *            If "true", includes the location information in the generated JSON.
      * @param properties
@@ -866,6 +887,11 @@ public final class JsonLayout extends AbstractJacksonLayout {
      * @param eventEol
      *            If "true", forces an EOL after each log event (even if compact is "true"), defaults to "false". This
      *            allows one even per line, even in compact mode.
+     * @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 JSON Layout.
@@ -873,28 +899,31 @@ public final class JsonLayout extends AbstractJacksonLayout {
     @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 = "complete", defaultBoolean = false) final boolean complete,
             @PluginAttribute(value = "compact", defaultBoolean = false) final boolean compact,
             @PluginAttribute(value = "eventEol", defaultBoolean = false) final boolean eventEol,
+            @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 JsonLayout(locationInfo, properties, complete, compact, eventEol, charset);
+        return new JsonLayout(config, locationInfo, properties, complete, compact, eventEol, headerPattern, footerPattern, charset);
     }
 
     /**
-     * Creates a JSON Layout using the default settings.
+     * Creates a JSON Layout using the default settings. Useful for testing.
      *
      * @return A JSON Layout.
      */
     public static AbstractJacksonLayout createDefaultLayout() {
-        return new JsonLayout(false, false, false, false, false, StandardCharsets.UTF_8);
+        return new JsonLayout(new DefaultConfiguration(), false, false, false, false, false, DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8);
     }
 
     @Override
-    public void toSerializable(final LogEvent event, Writer writer) throws IOException {
+    public void toSerializable(final LogEvent event, final Writer writer) throws IOException {
         if (complete && eventCount > 0) {
             writer.append(", ");
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
index 0503fc8..518f6a4 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/PatternLayout.java
@@ -26,7 +26,6 @@ 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.LoggerConfig;
 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;
@@ -39,7 +38,6 @@ import org.apache.logging.log4j.core.pattern.LogEventPatternConverter;
 import org.apache.logging.log4j.core.pattern.PatternFormatter;
 import org.apache.logging.log4j.core.pattern.PatternParser;
 import org.apache.logging.log4j.core.pattern.RegexReplacement;
-import org.apache.logging.log4j.core.util.StringEncoder;
 import org.apache.logging.log4j.util.Strings;
 
 /**
@@ -89,15 +87,6 @@ public final class PatternLayout extends AbstractStringLayout {
 
     private final Serializer eventSerializer;
 
-    private final Serializer headerSerializer;
-
-    private final Serializer footerSerializer;
-
-    /**
-     * The current Configuration.
-     */
-    private final Configuration config;
-
     /**
      * Constructs a EnhancedPatternLayout using the supplied conversion pattern.
      *
@@ -116,16 +105,15 @@ public final class PatternLayout extends AbstractStringLayout {
     private PatternLayout(final Configuration config, final RegexReplacement replace, final String eventPattern,
             final PatternSelector patternSelector, final Charset charset, final boolean alwaysWriteExceptions,
             final boolean noConsoleNoAnsi, final String headerPattern, final String footerPattern) {
-        super(charset, StringEncoder.toBytes(headerPattern, charset), StringEncoder.toBytes(footerPattern, charset));
+        super(config, charset,
+                createSerializer(config, replace, headerPattern, null, patternSelector, alwaysWriteExceptions,
+                        noConsoleNoAnsi),
+                createSerializer(config, replace, footerPattern, null, patternSelector, alwaysWriteExceptions,
+                        noConsoleNoAnsi));
         this.conversionPattern = eventPattern;
         this.patternSelector = patternSelector;
-        this.config = config;
-        this.eventSerializer = createSerializer(config, replace, eventPattern, DEFAULT_CONVERSION_PATTERN, patternSelector,
-                alwaysWriteExceptions, noConsoleNoAnsi);
-        this.headerSerializer = createSerializer(config, replace, headerPattern, null, patternSelector,
-                alwaysWriteExceptions, noConsoleNoAnsi);
-        this.footerSerializer = createSerializer(config, replace, footerPattern, null, patternSelector,
-                alwaysWriteExceptions, noConsoleNoAnsi);
+        this.eventSerializer = createSerializer(config, replace, eventPattern, DEFAULT_CONVERSION_PATTERN,
+                patternSelector, alwaysWriteExceptions, noConsoleNoAnsi);
     }
 
     public static Serializer createSerializer(final Configuration configuration, final RegexReplacement replace,
@@ -148,27 +136,6 @@ public final class PatternLayout extends AbstractStringLayout {
         return new PatternSelectorSerializer(patternSelector, replace);
     }
 
-    @Override
-    public byte[] getHeader() {
-        return serializeHeaderFooter(headerSerializer);
-    }
-
-    @Override
-    public byte[] getFooter() {
-        return serializeHeaderFooter(footerSerializer);
-    }
-
-    private byte[] serializeHeaderFooter(final Serializer serializer) {
-        if (serializer == null) {
-            return null;
-        }
-        final LoggerConfig rootLogger = config.getRootLogger();
-        // Using "" for the FQCN, does it matter?
-        final LogEvent logEvent = rootLogger.getLogEventFactory().createEvent(rootLogger.getName(), null, Strings.EMPTY,
-                rootLogger.getLevel(), null, null, null);
-        return StringEncoder.toBytes(serializer.toSerializable(logEvent), getCharset());
-    }
-
     /**
      * Gets the conversion pattern.
      *
@@ -279,11 +246,6 @@ public final class PatternLayout extends AbstractStringLayout {
             .build();
     }
 
-    public interface Serializer {
-        
-        String toSerializable(final LogEvent event);        
-    }
-
     private static class PatternSerializer implements Serializer {
 
         private final PatternFormatter[] formatters;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
index f60c1b2..6d2349d 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/SerializedLayout.java
@@ -48,7 +48,7 @@ public final class SerializedLayout extends AbstractLayout<LogEvent> {
     }
 
     private SerializedLayout() {
-        super(null, null);
+        super(null, null, null);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
index 5badaca..8e01bd3 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/XmlLayout.java
@@ -197,7 +197,7 @@ public final class XmlLayout extends AbstractJacksonLayout {
     private static final String ROOT_TAG = "Events";
 
     protected XmlLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact, final Charset charset) {
-        super(new JacksonFactory.XML().newWriter(locationInfo, properties, compact), charset, compact, complete, false);
+        super(null, new JacksonFactory.XML().newWriter(locationInfo, properties, compact), charset, compact, complete, false, null, null);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
index 67f0932..2f15042 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/net/SmtpManager.java
@@ -42,10 +42,8 @@ import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.appender.AbstractManager;
 import org.apache.logging.log4j.core.appender.ManagerFactory;
 import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.DefaultConfiguration;
-import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
+import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
 import org.apache.logging.log4j.core.layout.PatternLayout;
-import org.apache.logging.log4j.core.layout.PatternLayout.Serializer;
 import org.apache.logging.log4j.core.util.CyclicBuffer;
 import org.apache.logging.log4j.core.util.NameUtil;
 import org.apache.logging.log4j.core.util.NetUtils;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvLogEventLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvLogEventLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvLogEventLayoutTest.java
index f0f6d95..688cb42 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvLogEventLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/CsvLogEventLayoutTest.java
@@ -64,12 +64,21 @@ public class CsvLogEventLayoutTest {
 
     @Test
     public void testCustomCharset() {
-        final AbstractCsvLayout layout = CsvLogEventLayout.createLayout("Excel", null, null, null, null, null, null,
-                StandardCharsets.UTF_16, null, null);
+        final AbstractCsvLayout layout = CsvLogEventLayout.createLayout(null, "Excel", null, null, null, null, null,
+                null, StandardCharsets.UTF_16, null, null);
         assertEquals("text/csv; charset=UTF-16", layout.getContentType());
     }
 
     @Test
+    public void testHeaderFooter() {
+        final String header = "# Header";
+        final String footer = "# Footer ";
+        final AbstractCsvLayout layout = CsvLogEventLayout.createLayout(ctx.getConfiguration(), "Excel", null, null,
+                null, null, null, null, null, header, footer);
+        testLayout(CSVFormat.DEFAULT, layout, header, footer);
+    }
+
+    @Test
     public void testDefaultCharset() {
         final AbstractCsvLayout layout = CsvLogEventLayout.createDefaultLayout();
         assertEquals(StandardCharsets.UTF_8, layout.getCharset());
@@ -82,7 +91,10 @@ public class CsvLogEventLayoutTest {
     }
 
     private void testLayout(final CSVFormat format) {
-        final AbstractCsvLayout layout = CsvLogEventLayout.createLayout(format);
+        testLayout(format, CsvLogEventLayout.createLayout(format), null, null);
+    }
+
+    private void testLayout(final CSVFormat format, final AbstractCsvLayout layout, String header, String footer) {
         final Map<String, Appender> appenders = root.getAppenders();
         for (final Appender appender : appenders.values()) {
             root.removeAppender(appender);
@@ -100,13 +112,35 @@ public class CsvLogEventLayoutTest {
         appender.stop();
 
         final List<String> list = appender.getMessages();
-        final String event0 = list.get(0);
+        final boolean hasHeaderSerializer = layout.getHeaderSerializer() != null;
+        final boolean hasFooterSerializer = layout.getFooterSerializer() != null;
+        final int headerOffset = hasHeaderSerializer ? 1 : 0;
+        final String event0 = list.get(0 + headerOffset);
+        final String event1 = list.get(1 + headerOffset);
         final char del = format.getDelimiter();
         Assert.assertTrue(event0, event0.contains(del + "DEBUG" + del));
         final String quote = del == ',' ? "\"" : "";
         Assert.assertTrue(event0, event0.contains(del + quote + "one=1, two=2, three=3" + quote + del));
-        final String event1 = list.get(1);
         Assert.assertTrue(event1, event1.contains(del + "INFO" + del));
+        
+        if (hasHeaderSerializer && header == null) {
+            Assert.fail();
+        }
+        if (!hasHeaderSerializer && header != null) {
+            Assert.fail();
+        }
+        if (hasFooterSerializer && footer == null) {
+            Assert.fail();
+        }
+        if (!hasFooterSerializer && footer != null) {
+            Assert.fail();
+        }
+        if (hasHeaderSerializer) {
+            Assert.assertEquals(list.toString(), header, list.get(0));
+        }
+        if (hasFooterSerializer) {
+            Assert.assertEquals(list.toString(), footer, list.get(list.size() - 1));
+        }
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/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 0bbe3c6..27a7318 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
@@ -65,8 +65,8 @@ public class CsvParameterLayoutTest {
 
     @Test
     public void testCustomCharset() {
-        final AbstractCsvLayout layout = CsvParameterLayout.createLayout("Excel", null, null, null, null, null, null,
-                StandardCharsets.UTF_16, null, null);
+        final AbstractCsvLayout layout = CsvParameterLayout.createLayout(null, "Excel", null, null, null, null, null,
+                null, StandardCharsets.UTF_16, null, null);
         assertEquals("text/csv; charset=UTF-16", layout.getContentType());
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
index 87b075c..22b017f 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/JsonLayoutTest.java
@@ -30,6 +30,7 @@ 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.Log4jJsonObjectMapper;
@@ -105,8 +106,8 @@ public class JsonLayoutTest {
     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 = JsonLayout.createLayout(includeSource,
-                includeContext, false, compact, eventEol, StandardCharsets.UTF_8);
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(null, includeSource,
+                includeContext, false, compact, eventEol, null, null, StandardCharsets.UTF_8);
         final String str = layout.toSerializable(expected);
         // System.out.println(str);
         final String propSep = this.toPropertySeparator(compact);
@@ -176,8 +177,9 @@ public class JsonLayoutTest {
         for (final Appender appender : appenders.values()) {
             this.rootLogger.removeAppender(appender);
         }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
         // set up appender
-        final AbstractJacksonLayout layout = JsonLayout.createLayout(true, true, true, false, false, null);
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(configuration, true, true, true, false, false, null, null, null);
         final ListAppender appender = new ListAppender("List", null, layout, true, false);
         appender.start();
 
@@ -211,8 +213,10 @@ public class JsonLayoutTest {
         for (final Appender appender : appenders.values()) {
             this.rootLogger.removeAppender(appender);
         }
+        final Configuration configuration = rootLogger.getContext().getConfiguration();
         // set up appender
-        final AbstractJacksonLayout layout = JsonLayout.createLayout(true, true, true, false, false, null);
+        // Use [[ and ]] to test header and footer (instead of [ and ])
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(configuration, true, true, true, false, false, "[[", "]]", null);
         final ListAppender appender = new ListAppender("List", null, layout, true, false);
         appender.start();
 
@@ -239,7 +243,7 @@ public class JsonLayoutTest {
 
         final List<String> list = appender.getMessages();
 
-        this.checkAt("[", 0, list);
+        this.checkAt("[[", 0, list);
         this.checkAt("{", 1, list);
         this.checkContains("\"loggerFqcn\" : \"" + AbstractLogger.class.getName() + "\",", list);
         this.checkContains("\"level\" : \"DEBUG\",", list);
@@ -251,7 +255,8 @@ public class JsonLayoutTest {
 
     @Test
     public void testLayoutLoggerName() throws Exception {
-        final AbstractJacksonLayout layout = JsonLayout.createLayout(false, false, false, true, false, StandardCharsets.UTF_8);
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(null, false, false, false, true, false, null, null,
+                StandardCharsets.UTF_8);
         final Log4jLogEvent expected = Log4jLogEvent.newBuilder() //
                 .setLoggerName("a.B") //
                 .setLoggerFqcn("f.q.c.n") //

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/AbstractSocketServerTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/AbstractSocketServerTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/AbstractSocketServerTest.java
index 06adc8a..ee5c2de 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/AbstractSocketServerTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/net/server/AbstractSocketServerTest.java
@@ -78,7 +78,7 @@ public abstract class AbstractSocketServerTest {
     }
 
     protected Layout<String> createJsonLayout() {
-        return JsonLayout.createLayout(true, true, false, false, false, null);
+        return JsonLayout.createLayout(null, true, true, false, false, false, null, null, null);
     }
 
     protected abstract Layout<? extends Serializable> createLayout();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/75d33d96/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3182a0c..d6de059 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,12 @@
       <action issue="LOG4J2-1237" dev="ggregory" type="add" due-to="Mike Calmus, Gary Gregory">
         Make PatternLayout header and footer accept a pattern. 
       </action>
+      <action issue="LOG4J2-1244" dev="ggregory" type="add" due-to="Anshu Garg, Remko Popma, Gary Gregory">
+        Make header and footer values customizable in JSONLayout. 
+      </action>
+      <action issue="LOG4J2-1245" dev="ggregory" type="add">
+        Make CSV Layout header and footers accept patterns. 
+      </action>      
       <action issue="LOG4J2-1192" dev="ggregory" type="add" due-to="Jörg Bretschneider, Gary Gregory">
         Dynamic Subject for SMTP Appender.
       </action>