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> - * <Appenders> - * <Socket name="Graylog" protocol="udp" host="graylog.domain.com" port="12201"> - * <GelfLayout host="someserver" compressionType="ZLIB" compressionThreshold="1024"> - * <KeyValuePair key="additionalField1" value="additional value 1"/> - * <KeyValuePair key="additionalField2" value="$${ctx:key}"/> - * </GelfLayout> - * </Socket> - * </Appenders> - * </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"> <Appenders> @@ -209,6 +209,19 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3); </Socket> </Appenders> </pre> + <p> + Configure as follows to send to a Graylog 2.x server with TCP: + </p> + <pre class="prettyprint linenums"> + <Appenders> + <Socket name="Graylog" protocol="tcp" host="graylog.domain.com" port="12201"> + <GelfLayout host="someserver" compressionType="OFF" includeNullDelimiter="true"> + <KeyValuePair key="additionalField1" value="constant value"/> + <KeyValuePair key="additionalField2" value="${dollar}${dollar}{ctx:key}"/> + </GelfLayout> + </Socket> + </Appenders> +</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>