This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch release-2.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git


The following commit(s) were added to refs/heads/release-2.x by this push:
     new 303045d  [LOG4J2-2337] Allow custom end-of-line with JsonLayout (2.x 
branch) (#264)
303045d is described below

commit 303045d1602bd2bd73cf6a1e60026830369389ba
Author: Patrice Ferrot <[email protected]>
AuthorDate: Tue Apr 23 15:09:06 2019 +0200

    [LOG4J2-2337] Allow custom end-of-line with JsonLayout (2.x branch) (#264)
    
    * Allow custom end-of-line with JsonLayout (fix for LOG4J2-2337)
    
    * Added justification for JsonLayout constructor change
---
 log4j-core/revapi.json                             |  6 +++++
 .../log4j/core/layout/AbstractJacksonLayout.java   | 18 +++++++++++---
 .../logging/log4j/core/layout/JsonLayout.java      | 14 +++++------
 .../logging/log4j/core/layout/XmlLayout.java       | 12 ++++-----
 .../logging/log4j/core/layout/YamlLayout.java      | 12 ++++-----
 .../logging/log4j/core/layout/JsonLayoutTest.java  | 29 ++++++++++++++++------
 src/site/xdoc/manual/layouts.xml.vm                |  8 ++++++
 7 files changed, 69 insertions(+), 30 deletions(-)

diff --git a/log4j-core/revapi.json b/log4j-core/revapi.json
index ae62904..fd2438b 100644
--- a/log4j-core/revapi.json
+++ b/log4j-core/revapi.json
@@ -77,6 +77,12 @@
         "old": "method java.net.Socket 
org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.lang.String,
 int, org.apache.logging.log4j.core.net.SocketOptions, int) throws 
java.io.IOException",
         "new": "method java.net.Socket 
org.apache.logging.log4j.core.net.TcpSocketManager::createSocket(java.net.InetSocketAddress)
 throws java.io.IOException",
         "justification": "LOG4J2-2586 - Support the host name resolving to 
mulitple ip addresses"
+      },
+      {
+        "code": "java.method.numberOfParametersChanged",
+        "old": "method void 
org.apache.logging.log4j.core.layout.JsonLayout::<init>(org.apache.logging.log4j.core.config.Configuration,
 boolean, boolean, boolean, boolean, boolean, boolean, java.lang.String, 
java.lang.String, java.nio.charset.Charset, boolean)",
+        "new": "method void 
org.apache.logging.log4j.core.layout.JsonLayout::<init>(org.apache.logging.log4j.core.config.Configuration,
 boolean, boolean, boolean, boolean, boolean, boolean, java.lang.String, 
java.lang.String, java.lang.String, java.nio.charset.Charset, boolean)",
+        "justification": "LOG4J2-2337 - Allow to specify custom end-of-line 
for JSON layout"
       }
     ]
   }
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 2e6f652..2e5e7f4 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
@@ -52,6 +52,9 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
         private boolean eventEol;
 
         @PluginBuilderAttribute
+        private String endOfLine;
+
+        @PluginBuilderAttribute
         private boolean compact;
 
         @PluginBuilderAttribute
@@ -83,6 +86,10 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
             return eventEol;
         }
 
+        public String getEndOfLine() {
+            return endOfLine;
+        }
+
         public boolean isCompact() {
             return compact;
         }
@@ -122,6 +129,11 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
             return asBuilder();
         }
 
+        public B setEndOfLine(final String endOfLine) {
+            this.endOfLine = endOfLine;
+            return asBuilder();
+        }
+
         public B setCompact(final boolean compact) {
             this.compact = compact;
             return asBuilder();
@@ -201,18 +213,18 @@ abstract class AbstractJacksonLayout extends 
AbstractStringLayout {
     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, final boolean 
includeNullDelimiter) {
-        this(config, objectWriter, charset, compact, complete, eventEol, 
headerSerializer, footerSerializer, includeNullDelimiter, null);
+        this(config, objectWriter, charset, compact, complete, eventEol, null, 
headerSerializer, footerSerializer, includeNullDelimiter, null);
     }
 
     protected AbstractJacksonLayout(final Configuration config, final 
ObjectWriter objectWriter, final Charset charset,
-            final boolean compact, final boolean complete, final boolean 
eventEol, final Serializer headerSerializer,
+            final boolean compact, final boolean complete, final boolean 
eventEol, final String endOfLine, final Serializer headerSerializer,
             final Serializer footerSerializer, final boolean 
includeNullDelimiter,
             final KeyValuePair[] additionalFields) {
         super(config, charset, headerSerializer, footerSerializer);
         this.objectWriter = objectWriter;
         this.compact = compact;
         this.complete = complete;
-        this.eol = compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL;
+        this.eol = endOfLine != null ? endOfLine : compact && !eventEol ? 
COMPACT_EOL : DEFAULT_EOL;
         this.includeNullDelimiter = includeNullDelimiter;
         this.additionalFields = prepareAdditionalFields(config, 
additionalFields);
     }
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 fbbd597..679f55c 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
@@ -97,7 +97,7 @@ public final class JsonLayout extends AbstractJacksonLayout {
             final String headerPattern = toStringOrNull(getHeader());
             final String footerPattern = toStringOrNull(getFooter());
             return new JsonLayout(getConfiguration(), isLocationInfo(), 
isProperties(), encodeThreadContextAsList,
-                    isComplete(), isCompact(), getEventEol(), headerPattern, 
footerPattern, getCharset(),
+                    isComplete(), isCompact(), getEventEol(), getEndOfLine(), 
headerPattern, footerPattern, getCharset(),
                     isIncludeStacktrace(), isStacktraceAsString(), 
isIncludeNullDelimiter(),
                     getAdditionalFields(), getObjectMessageAsJsonObject());
         }
@@ -138,11 +138,11 @@ public final class JsonLayout extends 
AbstractJacksonLayout {
     @Deprecated
     protected JsonLayout(final Configuration config, final boolean 
locationInfo, final boolean properties,
             final boolean encodeThreadContextAsList,
-            final boolean complete, final boolean compact, final boolean 
eventEol, final String headerPattern,
+            final boolean complete, final boolean compact, final boolean 
eventEol, final String endOfLine,final String headerPattern,
             final String footerPattern, final Charset charset, final boolean 
includeStacktrace) {
         super(config, new JacksonFactory.JSON(encodeThreadContextAsList, 
includeStacktrace, false, false).newWriter(
                 locationInfo, properties, compact),
-                charset, compact, complete, eventEol,
+                charset, compact, complete, eventEol, endOfLine,
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
                 false, null);
@@ -150,14 +150,14 @@ public final class JsonLayout extends 
AbstractJacksonLayout {
 
     private JsonLayout(final Configuration config, final boolean locationInfo, 
final boolean properties,
                        final boolean encodeThreadContextAsList,
-                       final boolean complete, final boolean compact, final 
boolean eventEol,
+                       final boolean complete, final boolean compact, final 
boolean eventEol, final String endOfLine,
                        final String headerPattern, final String footerPattern, 
final Charset charset,
                        final boolean includeStacktrace, final boolean 
stacktraceAsString,
                        final boolean includeNullDelimiter,
                        final KeyValuePair[] additionalFields, final boolean 
objectMessageAsJsonObject) {
         super(config, new JacksonFactory.JSON(encodeThreadContextAsList, 
includeStacktrace, stacktraceAsString, objectMessageAsJsonObject).newWriter(
                 locationInfo, properties, compact),
-                charset, compact, complete, eventEol,
+                charset, compact, complete, eventEol, endOfLine,
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
                 includeNullDelimiter,
@@ -265,7 +265,7 @@ public final class JsonLayout extends AbstractJacksonLayout 
{
             final boolean includeStacktrace) {
         final boolean encodeThreadContextAsList = properties && 
propertiesAsList;
         return new JsonLayout(config, locationInfo, properties, 
encodeThreadContextAsList, complete, compact, eventEol,
-                headerPattern, footerPattern, charset, includeStacktrace, 
false, false, null, false);
+                null, headerPattern, footerPattern, charset, 
includeStacktrace, false, false, null, false);
     }
 
     @PluginBuilderFactory
@@ -279,7 +279,7 @@ public final class JsonLayout extends AbstractJacksonLayout 
{
      * @return A JSON Layout.
      */
     public static JsonLayout createDefaultLayout() {
-        return new JsonLayout(new DefaultConfiguration(), false, false, false, 
false, false, false,
+        return new JsonLayout(new DefaultConfiguration(), false, false, false, 
false, false, false, null,
                 DEFAULT_HEADER, DEFAULT_FOOTER, StandardCharsets.UTF_8, true, 
false, false, null, false);
     }
 
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 c9cd886..94f6c40 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
@@ -75,7 +75,7 @@ public final class XmlLayout extends AbstractJacksonLayout {
         @Override
         public XmlLayout build() {
             return new XmlLayout(getConfiguration(), isLocationInfo(), 
isProperties(), isComplete(),
-                    isCompact(), getCharset(), isIncludeStacktrace(), 
isStacktraceAsString(),
+                    isCompact(), getEndOfLine(), getCharset(), 
isIncludeStacktrace(), isStacktraceAsString(),
                     isIncludeNullDelimiter(), getAdditionalFields());
         }
     }
@@ -86,17 +86,17 @@ public final class XmlLayout extends AbstractJacksonLayout {
     @Deprecated
     protected XmlLayout(final boolean locationInfo, final boolean properties, 
final boolean complete,
                         final boolean compact, final Charset charset, final 
boolean includeStacktrace) {
-        this(null, locationInfo, properties, complete, compact, charset, 
includeStacktrace, false, false, null);
+        this(null, locationInfo, properties, complete, compact, null, charset, 
includeStacktrace, false, false, null);
     }
 
     private XmlLayout(final Configuration config, final boolean locationInfo, 
final boolean properties,
-                      final boolean complete, final boolean compact, final 
Charset charset,
+                      final boolean complete, final boolean compact, final 
String endOfLine, final Charset charset,
                       final boolean includeStacktrace, final boolean 
stacktraceAsString,
                       final boolean includeNullDelimiter,
                       final KeyValuePair[] additionalFields) {
         super(config, new JacksonFactory.XML(includeStacktrace, 
stacktraceAsString).newWriter(
             locationInfo, properties, compact),
-            charset, compact, complete, false, null, null, 
includeNullDelimiter,
+            charset, compact, complete, false, endOfLine, null, null, 
includeNullDelimiter,
             additionalFields);
     }
 
@@ -188,7 +188,7 @@ public final class XmlLayout extends AbstractJacksonLayout {
             final boolean compact,
             final Charset charset,
             final boolean includeStacktrace) {
-        return new XmlLayout(null, locationInfo, properties, complete, 
compact, charset, includeStacktrace, false,
+        return new XmlLayout(null, locationInfo, properties, complete, 
compact, null, charset, includeStacktrace, false,
                 false, null);
     }
 
@@ -203,6 +203,6 @@ public final class XmlLayout extends AbstractJacksonLayout {
      * @return an XML Layout.
      */
     public static XmlLayout createDefaultLayout() {
-        return new XmlLayout(null, false, false, false, false, 
StandardCharsets.UTF_8, true, false, false, null);
+        return new XmlLayout(null, false, false, false, false, null, 
StandardCharsets.UTF_8, true, false, false, null);
     }
 }
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 0245cd8..4cf803c 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
@@ -67,7 +67,7 @@ public final class YamlLayout extends AbstractJacksonLayout {
             final String headerPattern = toStringOrNull(getHeader());
             final String footerPattern = toStringOrNull(getFooter());
             return new YamlLayout(getConfiguration(), isLocationInfo(), 
isProperties(), isComplete(),
-                    isCompact(), getEventEol(), headerPattern, footerPattern, 
getCharset(),
+                    isCompact(), getEventEol(), getEndOfLine(), headerPattern, 
footerPattern, getCharset(),
                     isIncludeStacktrace(), isStacktraceAsString(), 
isIncludeNullDelimiter(),
                     getAdditionalFields());
         }
@@ -81,20 +81,20 @@ public final class YamlLayout extends AbstractJacksonLayout 
{
             final boolean complete, final boolean compact, final boolean 
eventEol, final String headerPattern,
             final String footerPattern, final Charset charset, final boolean 
includeStacktrace) {
         super(config, new JacksonFactory.YAML(includeStacktrace, 
false).newWriter(locationInfo, properties, compact),
-                charset, compact, complete, eventEol,
+                charset, compact, complete, eventEol, null,
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
                 false, null);
     }
 
     private YamlLayout(final Configuration config, final boolean locationInfo, 
final boolean properties,
-                       final boolean complete, final boolean compact, final 
boolean eventEol,
+                       final boolean complete, final boolean compact, final 
boolean eventEol, final String endOfLine,
                        final String headerPattern, final String footerPattern, 
final Charset charset,
                        final boolean includeStacktrace, final boolean 
stacktraceAsString,
                        final boolean includeNullDelimiter,
                        final KeyValuePair[] additionalFields) {
         super(config, new JacksonFactory.YAML(includeStacktrace, 
stacktraceAsString).newWriter(locationInfo, properties, compact),
-                charset, compact, complete, eventEol,
+                charset, compact, complete, eventEol, endOfLine,
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern).setDefaultPattern(DEFAULT_HEADER).build(),
                 
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern).setDefaultPattern(DEFAULT_FOOTER).build(),
                 includeNullDelimiter,
@@ -185,7 +185,7 @@ public final class YamlLayout extends AbstractJacksonLayout 
{
             final String footerPattern,
             final Charset charset,
             final boolean includeStacktrace) {
-        return new YamlLayout(config, locationInfo, properties, false, false, 
true, headerPattern, footerPattern,
+        return new YamlLayout(config, locationInfo, properties, false, false, 
true, null, headerPattern, footerPattern,
                 charset, includeStacktrace, false, false, null);
     }
 
@@ -200,7 +200,7 @@ public final class YamlLayout extends AbstractJacksonLayout 
{
      * @return A YAML Layout.
      */
     public static AbstractJacksonLayout createDefaultLayout() {
-        return new YamlLayout(new DefaultConfiguration(), false, false, false, 
false, false, DEFAULT_HEADER,
+        return new YamlLayout(new DefaultConfiguration(), false, false, false, 
false, false, null, DEFAULT_HEADER,
                 DEFAULT_FOOTER, StandardCharsets.UTF_8, true, false, false, 
null);
     }
 }
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 9dfade0..7bdd4cc 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
@@ -133,7 +133,7 @@ public class JsonLayoutTest {
     }
 
     private void testAllFeatures(final boolean locationInfo, final boolean 
compact, final boolean eventEol,
-            final boolean includeContext, final boolean contextMapAslist, 
final boolean includeStacktrace)
+            final String endOfLine, final boolean includeContext, final 
boolean contextMapAslist, final boolean includeStacktrace)
             throws Exception {
         final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
         // @formatter:off
@@ -144,16 +144,24 @@ public class JsonLayoutTest {
                 .setComplete(false)
                 .setCompact(compact)
                 .setEventEol(eventEol)
+                .setEndOfLine(endOfLine)
                 .setCharset(StandardCharsets.UTF_8)
                 .setIncludeStacktrace(includeStacktrace)
                 .build();
         // @formatter:off
         final String str = layout.toSerializable(expected);
         this.toPropertySeparator(compact);
-        // Just check for \n since \r might or might not be there.
-        assertEquals(str, !compact || eventEol, str.contains("\n"));
+        if (endOfLine == null) {
+            // Just check for \n since \r might or might not be there.
+            assertEquals(str, !compact || eventEol, str.contains("\n"));
+        }
+        else {
+            assertEquals(str, !compact || eventEol, str.contains(endOfLine));
+            assertEquals(str, compact && eventEol, str.endsWith(endOfLine));
+        }
         assertEquals(str, locationInfo, str.contains("source"));
         assertEquals(str, includeContext, str.contains("contextMap"));
+
         final Log4jLogEvent actual = new 
Log4jJsonObjectMapper(contextMapAslist, includeStacktrace, false, 
false).readValue(str, Log4jLogEvent.class);
         LogEventFixtures.assertEqualLogEvents(expected, actual, locationInfo, 
includeContext, includeStacktrace);
         if (includeContext) {
@@ -453,27 +461,32 @@ public class JsonLayoutTest {
 
     @Test
     public void testLocationOffCompactOffMdcOff() throws Exception {
-        this.testAllFeatures(false, false, false, false, false, true);
+        this.testAllFeatures(false, false, false, null, false, false, true);
     }
 
     @Test
     public void testLocationOnCompactOnMdcOn() throws Exception {
-        this.testAllFeatures(true, true, false, true, false, true);
+        this.testAllFeatures(true, true, false, null, true, false, true);
     }
 
     @Test
     public void testLocationOnCompactOnEventEolOnMdcOn() throws Exception {
-        this.testAllFeatures(true, true, true, true, false, true);
+        this.testAllFeatures(true, true, true, null, true, false, true);
     }
 
     @Test
     public void testLocationOnCompactOnEventEolOnMdcOnMdcAsList() throws 
Exception {
-        this.testAllFeatures(true, true, true, true, true, true);
+        this.testAllFeatures(true, true, true, null, true, true, true);
     }
 
     @Test
     public void testExcludeStacktrace() throws Exception {
-        this.testAllFeatures(false, false, false, false, false, false);
+        this.testAllFeatures(false, false, false, null, false, false, false);
+    }
+
+    @Test
+    public void testLocationOnCustomEndOfLine() throws Exception {
+        this.testAllFeatures(true, true, true, "CUSTOM_END_OF_LINE", true, 
false, true);
     }
 
     @Test
diff --git a/src/site/xdoc/manual/layouts.xml.vm 
b/src/site/xdoc/manual/layouts.xml.vm
index 0508966..73d9722 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -429,6 +429,14 @@ logger.debug("one={}, two={}, three={}", 1, 2, 3);
               </td>
             </tr>
             <tr>
+              <td>endOfLine</td>
+              <td>String</td>
+              <td>
+                If set, overrides the default end-of-line string. E.g. set it 
to "\n" and use with eventEol=true and compact=true
+                to have one record per line separated by "\n" instead of 
"\r\n". Defaults to null (i.e. not set).
+              </td>
+            </tr>
+            <tr>
               <td>complete</td>
               <td>boolean</td>
               <td>If true, the appender includes the JSON header and footer, 
and comma between records. Defaults to false.</td>

Reply via email to