You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2015/01/17 06:46:06 UTC

logging-log4j2 git commit: [LOG4J2-941] Allow JSON layout to create one compact log record per line.

Repository: logging-log4j2
Updated Branches:
  refs/heads/master 77505979e -> 5ad7d8124


[LOG4J2-941] Allow JSON layout to create one compact log record per
line.

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

Branch: refs/heads/master
Commit: 5ad7d8124360b5cf5aa26d377dbf8c0057d4d11b
Parents: 7750597
Author: Gary Gregory <ga...@gmail.com>
Authored: Sat Jan 17 00:45:34 2015 -0500
Committer: Gary Gregory <ga...@gmail.com>
Committed: Sat Jan 17 00:45:34 2015 -0500

----------------------------------------------------------------------
 .../core/layout/AbstractJacksonLayout.java      |  6 +--
 .../logging/log4j/core/layout/JsonLayout.java   | 27 ++++++++-----
 .../logging/log4j/core/layout/XmlLayout.java    |  2 +-
 .../core/appender/ConsoleAppenderTest.java      | 41 +++++++++++++++++++-
 .../log4j/core/layout/JsonLayoutTest.java       | 21 ++++++----
 .../net/server/AbstractSocketServerTest.java    |  2 +-
 src/changes/changes.xml                         |  3 ++
 src/site/xdoc/manual/layouts.xml.vm             |  8 ++++
 8 files changed, 86 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/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 0215de8..bed0e08 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
@@ -34,12 +34,12 @@ 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) {
+    protected AbstractJacksonLayout(final ObjectWriter objectWriter, final Charset charset, final boolean compact, final boolean complete, boolean eventEol) {
         super(charset);
         this.objectWriter = objectWriter;
         this.compact = compact;
         this.complete = complete;
-        this.eol = compact ? COMPACT_EOL : DEFAULT_EOL;
+        this.eol = compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL;
     }
 
     /**
@@ -51,7 +51,7 @@ abstract class AbstractJacksonLayout extends AbstractStringLayout {
     @Override
     public String toSerializable(final LogEvent event) {
         try {
-            return this.objectWriter.writeValueAsString(event);
+            return this.objectWriter.writeValueAsString(event) + eol;
         } catch (final JsonProcessingException e) {
             // Should this be an ISE or IAE?
             LOGGER.error(e);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/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 97a916e..be0d96d 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
@@ -799,8 +799,8 @@ public final class JsonLayout extends AbstractJacksonLayout {
     private static final long serialVersionUID = 1L;
 
     protected JsonLayout(final boolean locationInfo, final boolean properties, final boolean complete, final boolean compact,
-            final Charset charset) {
-        super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete);
+            boolean eventEol, final Charset charset) {
+        super(new JacksonFactory.JSON().newWriter(locationInfo, properties, compact), charset, compact, complete, eventEol);
     }
 
     /**
@@ -850,11 +850,19 @@ public final class JsonLayout extends AbstractJacksonLayout {
     /**
      * Creates a JSON Layout.
      *
-     * @param locationInfo If "true", includes the location information in the generated JSON.
-     * @param properties If "true", includes the thread context in the generated JSON.
-     * @param complete If "true", includes the JSON header and footer, defaults to "false".
-     * @param compact If "true", does not use end-of-lines and indentation, defaults to "false".
-     * @param charset The character set to use, if {@code null}, uses "UTF-8".
+     * @param locationInfo
+     *        If "true", includes the location information in the generated JSON.
+     * @param properties
+     *        If "true", includes the thread context in the generated JSON.
+     * @param complete
+     *        If "true", includes the JSON header and footer, defaults to "false".
+     * @param compact
+     *        If "true", does not use end-of-lines and indentation, defaults to "false".
+     * @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 charset
+     *        The character set to use, if {@code null}, uses "UTF-8".
      * @return A JSON Layout.
      */
     @PluginFactory
@@ -864,10 +872,11 @@ public final class JsonLayout extends AbstractJacksonLayout {
             @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 = "charset", defaultString = "UTF-8") final Charset charset
             // @formatter:on
     ) {
-        return new JsonLayout(locationInfo, properties, complete, compact, charset);
+        return new JsonLayout(locationInfo, properties, complete, compact, eventEol, charset);
     }
 
     /**
@@ -876,6 +885,6 @@ public final class JsonLayout extends AbstractJacksonLayout {
      * @return A JSON Layout.
      */
     public static AbstractJacksonLayout createDefaultLayout() {
-        return new JsonLayout(false, false, false, false, Charsets.UTF_8);
+        return new JsonLayout(false, false, false, false, false, Charsets.UTF_8);
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/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 df83cca..e0c64a4 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
@@ -194,7 +194,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);
+        super(new JacksonFactory.XML().newWriter(locationInfo, properties, compact), charset, compact, complete, false);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
index 78213d1..3c5fe35 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderTest.java
@@ -16,26 +16,36 @@
  */
 package org.apache.logging.log4j.core.appender;
 
+import static org.easymock.EasyMock.anyInt;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 
 import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Layout;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
+import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.message.SimpleMessage;
+import org.easymock.EasyMockSupport;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import static org.junit.Assert.*;
-
 /**
  *
  */
 public class ConsoleAppenderTest {
 
     private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    EasyMockSupport mocks = new EasyMockSupport();
+    PrintStream psMock = mocks.createMock("psMock", PrintStream.class);
 
     @BeforeClass
     public static void before() {
@@ -48,6 +58,33 @@ public class ConsoleAppenderTest {
     }
 
     @Test
+    public void testConsoleStreamManagerDoesNotClose() {
+        final PrintStream ps = System.out;
+
+        psMock.write((byte[]) anyObject(), anyInt(), anyInt());
+        expectLastCall().anyTimes();
+        psMock.flush();
+
+        mocks.replayAll();
+        System.setOut(psMock);
+        final Layout<String> layout = PatternLayout.createLayout(null, null, null, null, false, false, null, null);
+        final ConsoleAppender app = ConsoleAppender.createAppender(layout, null, "SYSTEM_OUT", "Console", "false",
+                "false");
+        app.start();
+        assertTrue("Appender did not start", app.isStarted());
+
+        final LogEvent event = new Log4jLogEvent("TestLogger", null, ConsoleAppenderTest.class.getName(), Level.INFO,
+                new SimpleMessage("Test"), null);
+        app.append(event);
+
+        app.stop();
+        assertFalse("Appender did not stop", app.isStarted());
+
+        System.setOut(ps);
+        mocks.verifyAll();
+    }
+    
+    @Test
     public void testFollow() {
         final PrintStream ps = System.out;
         final ConsoleAppender app = ConsoleAppender.newBuilder()

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/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 368ead6..b043660 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
@@ -101,16 +101,16 @@ public class JsonLayoutTest {
         assertTrue(str, str.contains(DQUOTE + name + DQUOTE + propSep));
     }
 
-    private void testAllFeatures(final boolean includeSource, final boolean compact, final boolean includeContext)
+    private void testAllFeatures(final boolean includeSource, final boolean compact, boolean eventEol, final boolean includeContext)
             throws Exception {
         final Log4jLogEvent expected = LogEventFixtures.createLogEvent();
         final AbstractJacksonLayout layout = JsonLayout.createLayout(includeSource,
-                includeContext, false, compact, Charsets.UTF_8);
+                includeContext, false, compact, eventEol, Charsets.UTF_8);
         final String str = layout.toSerializable(expected);
         // System.out.println(str);
         final String propSep = this.toPropertySeparator(compact);
         // Just check for \n since \r might or might not be there.
-        assertEquals(str, !compact, str.contains("\n"));
+        assertEquals(str, !compact || eventEol, str.contains("\n"));
         assertEquals(str, includeSource, str.contains("source"));
         assertEquals(str, includeContext, str.contains("contextMap"));
         final Log4jLogEvent actual = new Log4jJsonObjectMapper().readValue(str, Log4jLogEvent.class);
@@ -178,7 +178,7 @@ public class JsonLayoutTest {
             this.rootLogger.removeAppender(appender);
         }
         // set up appender
-        final AbstractJacksonLayout layout = JsonLayout.createLayout(true, true, true, false, null);
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(true, true, true, false, false, null);
         final ListAppender appender = new ListAppender("List", null, layout, true, false);
         appender.start();
 
@@ -213,7 +213,7 @@ public class JsonLayoutTest {
             this.rootLogger.removeAppender(appender);
         }
         // set up appender
-        final AbstractJacksonLayout layout = JsonLayout.createLayout(true, true, true, false, null);
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(true, true, true, false, false, null);
         final ListAppender appender = new ListAppender("List", null, layout, true, false);
         appender.start();
 
@@ -252,7 +252,7 @@ public class JsonLayoutTest {
 
     @Test
     public void testLayoutLoggerName() throws Exception {
-        final AbstractJacksonLayout layout = JsonLayout.createLayout(false, false, false, true, Charsets.UTF_8);
+        final AbstractJacksonLayout layout = JsonLayout.createLayout(false, false, false, true, false, Charsets.UTF_8);
         final Log4jLogEvent expected = Log4jLogEvent.createEvent("a.B", null, "f.q.c.n", Level.DEBUG, 
                 new SimpleMessage("M"), null, null, null, null, "threadName", null, 1);
         final String str = layout.toSerializable(expected);
@@ -264,12 +264,17 @@ public class JsonLayoutTest {
 
     @Test
     public void testLocationOffCompactOffMdcOff() throws Exception {
-        this.testAllFeatures(false, false, false);
+        this.testAllFeatures(false, false, false, false);
     }
 
     @Test
     public void testLocationOnCompactOnMdcOn() throws Exception {
-        this.testAllFeatures(true, true, true);
+        this.testAllFeatures(true, true, false, true);
+    }
+
+    @Test
+    public void testLocationOnCompactOnEventEolOnMdcOn() throws Exception {
+        this.testAllFeatures(true, true, true, true);
     }
 
     private String toPropertySeparator(final boolean compact) {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/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 f97b584..891e278 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
@@ -91,7 +91,7 @@ public abstract class AbstractSocketServerTest {
     }
 
     protected Layout<String> createJsonLayout() {
-        return JsonLayout.createLayout(true, true, false, false, null);
+        return JsonLayout.createLayout(true, true, false, false, false, null);
     }
 
     protected abstract Layout<? extends Serializable> createLayout();

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index edf5dfa..de831a2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -24,6 +24,9 @@
   </properties>
   <body>
     <release version="2.2" date="201?-??-??" description="GA Release 2.2">
+      <action issue="LOG4J2-941" dev="ggregory" type="add" due-to="Konstantinos Liakos">
+        Allow JSON layout to create one compact log record per line.
+      </action>
       <action issue="LOG4J2-933" dev="ggregory" type="add" due-to="ppiman at gmail.com">
         HTML layout should not use attribute minimalization for hr noshade.
       </action>

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/5ad7d812/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 a64c92c..dd4683a 100644
--- a/src/site/xdoc/manual/layouts.xml.vm
+++ b/src/site/xdoc/manual/layouts.xml.vm
@@ -116,6 +116,14 @@
               <td>If true, the appender does not use end-of-lines and indentation. Defaults to false.</td>
             </tr>
             <tr>
+              <td>eventEol</td>
+              <td>boolean</td>
+              <td>
+                If true, the appender appends an end-of-line after each record. Defaults to false.
+                Use with eventEol=true and compact=true to get one record per line.
+              </td>
+            </tr>
+            <tr>
               <td>complete</td>
               <td>boolean</td>
               <td>If true, the appender includes the JSON header and footer. Defaults to false.</td>