LOG4J2-1854 Support null byte delimiter in GelfLayout.

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

Branch: refs/heads/master
Commit: 01d0f5adee12146356d9574f3de52a273696825e
Parents: 595444d
Author: Mikael Ståldal <mikael.stal...@magine.com>
Authored: Wed Apr 26 11:46:11 2017 +0200
Committer: Mikael Ståldal <mikael.stal...@magine.com>
Committed: Wed Apr 26 11:46:11 2017 +0200

----------------------------------------------------------------------
 .../logging/log4j/core/layout/GelfLayout.java   | 44 ++++++++++++--------
 .../log4j/core/layout/GelfLayoutTest.java       | 20 +++++----
 src/changes/changes.xml                         |  3 ++
 src/site/xdoc/manual/layouts.xml.vm             | 21 +++++++++-
 4 files changed, 62 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/01d0f5ad/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
index 4518766..84970d2 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/layout/GelfLayout.java
@@ -57,20 +57,6 @@ import org.apache.logging.log4j.util.TriConsumer;
  * log event data is larger than 1024 bytes (the {@code compressionThreshold}).
  * This layout does not implement chunking.
  * </p>
- * <p>
- * Configure as follows to send to a Graylog 2.x server:
- * </p>
- *
- * <pre>
- * &lt;Appenders&gt;
- *        &lt;Socket name="Graylog" protocol="udp" host="graylog.domain.com" 
port="12201"&gt;
- *            &lt;GelfLayout host="someserver" compressionType="ZLIB" 
compressionThreshold="1024"&gt;
- *                &lt;KeyValuePair key="additionalField1" value="additional 
value 1"/&gt;
- *                &lt;KeyValuePair key="additionalField2" 
value="$${ctx:key}"/&gt;
- *            &lt;/GelfLayout&gt;
- *        &lt;/Socket&gt;
- * &lt;/Appenders&gt;
- * </pre>
  *
  * @see <a href="http://docs.graylog.org/en/latest/pages/gelf.html#gelf";>GELF 
specification</a>
  */
@@ -113,6 +99,7 @@ public final class GelfLayout extends AbstractStringLayout {
     private final String host;
     private final boolean includeStacktrace;
     private final boolean includeThreadContext;
+    private final boolean includeNullDelimiter;
 
     public static class Builder<B extends Builder<B>> extends 
AbstractStringLayout.Builder<B>
         implements org.apache.logging.log4j.core.util.Builder<GelfLayout> {
@@ -135,6 +122,9 @@ public final class GelfLayout extends AbstractStringLayout {
         @PluginBuilderAttribute
         private boolean includeThreadContext = true;
 
+        @PluginBuilderAttribute
+        private boolean includeNullDelimiter = false;
+
         public Builder() {
             super();
             setCharset(StandardCharsets.UTF_8);
@@ -142,7 +132,8 @@ public final class GelfLayout extends AbstractStringLayout {
 
         @Override
         public GelfLayout build() {
-            return new GelfLayout(getConfiguration(), host, additionalFields, 
compressionType, compressionThreshold, includeStacktrace, includeThreadContext);
+            return new GelfLayout(getConfiguration(), host, additionalFields, 
compressionType, compressionThreshold,
+                includeStacktrace, includeThreadContext, includeNullDelimiter);
         }
 
         public String getHost() {
@@ -165,6 +156,8 @@ public final class GelfLayout extends AbstractStringLayout {
             return includeThreadContext;
         }
 
+        public boolean isIncludeNullDelimiter() { return includeNullDelimiter; 
}
+
         public KeyValuePair[] getAdditionalFields() {
             return additionalFields;
         }
@@ -221,6 +214,17 @@ public final class GelfLayout extends AbstractStringLayout 
{
         }
 
         /**
+         * Whether to include NULL byte as delimiter after each event 
(optional, default to false).
+         * Useful for Graylog GELF TCP input.
+         *
+         * @return this builder
+         */
+        public B setIncludeNullDelimiter(boolean includeNullDelimiter) {
+            this.includeNullDelimiter = includeNullDelimiter;
+            return asBuilder();
+        }
+
+        /**
          * Additional fields to set on each log event.
          *
          * @return this builder
@@ -237,11 +241,11 @@ public final class GelfLayout extends 
AbstractStringLayout {
     @Deprecated
     public GelfLayout(final String host, final KeyValuePair[] 
additionalFields, final CompressionType compressionType,
                       final int compressionThreshold, final boolean 
includeStacktrace) {
-        this(null, host, additionalFields, compressionType, 
compressionThreshold, includeStacktrace, true);
+        this(null, host, additionalFields, compressionType, 
compressionThreshold, includeStacktrace, true, false);
     }
 
     private GelfLayout(final Configuration config, final String host, final 
KeyValuePair[] additionalFields, final CompressionType compressionType,
-               final int compressionThreshold, final boolean 
includeStacktrace, final boolean includeThreadContext) {
+               final int compressionThreshold, final boolean 
includeStacktrace, final boolean includeThreadContext, final boolean 
includeNullDelimiter) {
         super(config, StandardCharsets.UTF_8, null, null);
         this.host = host != null ? host : NetUtils.getLocalHostname();
         this.additionalFields = additionalFields != null ? additionalFields : 
new KeyValuePair[0];
@@ -256,6 +260,7 @@ public final class GelfLayout extends AbstractStringLayout {
         this.compressionThreshold = compressionThreshold;
         this.includeStacktrace = includeStacktrace;
         this.includeThreadContext = includeThreadContext;
+        this.includeNullDelimiter = includeNullDelimiter;
     }
 
     /**
@@ -273,7 +278,7 @@ public final class GelfLayout extends AbstractStringLayout {
             @PluginAttribute(value = "includeStacktrace",
                 defaultBoolean = true) final boolean includeStacktrace) {
             // @formatter:on
-        return new GelfLayout(null, host, additionalFields, compressionType, 
compressionThreshold, includeStacktrace, true);
+        return new GelfLayout(null, host, additionalFields, compressionType, 
compressionThreshold, includeStacktrace, true, false);
     }
 
     @PluginBuilderFactory
@@ -393,6 +398,9 @@ public final class GelfLayout extends AbstractStringLayout {
         }
         builder.append(Q);
         builder.append('}');
+        if (includeNullDelimiter) {
+            builder.append('\0');
+        }
         return builder;
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/01d0f5ad/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
index 73667ba..b8d4372 100644
--- 
a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
+++ 
b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/GelfLayoutTest.java
@@ -80,7 +80,7 @@ public class GelfLayoutTest {
     Logger root = ctx.getRootLogger();
 
     private void testCompressedLayout(final CompressionType compressionType, 
final boolean includeStacktrace,
-                                      final boolean includeThreadContext, 
String host) throws IOException {
+                                      final boolean includeThreadContext, 
String host, final boolean includeNullDelimiter) throws IOException {
         for (final Appender appender : root.getAppenders().values()) {
             root.removeAppender(appender);
         }
@@ -95,6 +95,7 @@ public class GelfLayoutTest {
             .setCompressionThreshold(1024)
             .setIncludeStacktrace(includeStacktrace)
             .setIncludeThreadContext(includeThreadContext)
+            .setIncludeNullDelimiter(includeNullDelimiter)
             .build();
         final ListAppender eventAppender = new ListAppender("Events", null, 
null, true, false);
         final ListAppender rawAppender = new ListAppender("Raw", null, layout, 
true, true);
@@ -219,32 +220,37 @@ public class GelfLayoutTest {
 
     @Test
     public void testLayoutGzipCompression() throws Exception {
-        testCompressedLayout(CompressionType.GZIP, true, true, HOSTNAME);
+        testCompressedLayout(CompressionType.GZIP, true, true, HOSTNAME, 
false);
     }
 
     @Test
     public void testLayoutNoCompression() throws Exception {
-        testCompressedLayout(CompressionType.OFF, true, true, HOSTNAME);
+        testCompressedLayout(CompressionType.OFF, true, true, HOSTNAME, false);
     }
 
     @Test
     public void testLayoutZlibCompression() throws Exception {
-        testCompressedLayout(CompressionType.ZLIB, true, true, HOSTNAME);
+        testCompressedLayout(CompressionType.ZLIB, true, true, HOSTNAME, 
false);
     }
 
     @Test
     public void testLayoutNoStacktrace() throws Exception {
-        testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME);
+        testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME, 
false);
     }
 
     @Test
     public void testLayoutNoThreadContext() throws Exception {
-        testCompressedLayout(CompressionType.OFF, true, false, HOSTNAME);
+        testCompressedLayout(CompressionType.OFF, true, false, HOSTNAME, 
false);
     }
 
     @Test
     public void testLayoutNoHost() throws Exception {
-        testCompressedLayout(CompressionType.OFF, true, true, null);
+        testCompressedLayout(CompressionType.OFF, true, true, null, false);
+    }
+
+    @Test
+    public void testLayoutNullDelimiter() throws Exception {
+        testCompressedLayout(CompressionType.OFF, false, true, HOSTNAME, true);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/01d0f5ad/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 01e133e..379c21e 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="2.9.0" date="2017-MM-DD" description="GA Release 2.9.0">
+      <action issue="LOG4J2-1854" dev="mikes" type="add" due-to="Xavier 
Jodoin">
+        Support null byte delimiter in GelfLayout.
+      </action>
       <action issue="LOG4J2-1359" dev="rgoers" type="add">
         Add support for Java 9 StackWalker.
       </action>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/01d0f5ad/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 fa9cb99..8c18d96 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -197,7 +197,7 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
             (the <code>compressionThreshold</code>). This layout does not 
implement chunking.
           </p>
           <p>
-            Configure as follows to send to a Graylog 2.x server:
+            Configure as follows to send to a Graylog 2.x server with UDP:
           </p>
           <pre class="prettyprint linenums">
   &lt;Appenders&gt;
@@ -209,6 +209,19 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
     &lt;/Socket&gt;
   &lt;/Appenders&gt;
 </pre>
+          <p>
+            Configure as follows to send to a Graylog 2.x server with TCP:
+          </p>
+          <pre class="prettyprint linenums">
+  &lt;Appenders&gt;
+    &lt;Socket name="Graylog" protocol="tcp" host="graylog.domain.com" 
port="12201"&gt;
+        &lt;GelfLayout host="someserver" compressionType="OFF" 
includeNullDelimiter="true"&gt;
+            &lt;KeyValuePair key="additionalField1" value="constant value"/&gt;
+            &lt;KeyValuePair key="additionalField2" 
value="${dollar}${dollar}{ctx:key}"/&gt;
+        &lt;/GelfLayout&gt;
+    &lt;/Socket&gt;
+  &lt;/Appenders&gt;
+</pre>
           <table>
             <tr>
               <th>Parameter Name</th>
@@ -242,6 +255,12 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
               <td>boolean</td>
               <td>Whether to include thread context as additional fields 
(optional, default to true).</td>
             </tr>
+            <tr>
+              <td>includeNullDelimiter</td>
+              <td>boolean</td>
+              <td>Whether to include NULL byte as delimiter after each event 
(optional, default to false).
+                  Useful for Graylog GELF TCP input.</td>
+            </tr>
             <caption align="top">GelfLayout Parameters</caption>
           </table>
            <p>

Reply via email to