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/03/08 17:35:41 UTC

[01/10] logging-log4j2 git commit: LOG4J2-1296 added initial unit tests for ParameterFormatter

Repository: logging-log4j2
Updated Branches:
  refs/heads/gelf-layout-gc-free 920cddd42 -> 58152b79b


LOG4J2-1296 added initial unit tests for ParameterFormatter


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

Branch: refs/heads/gelf-layout-gc-free
Commit: 8b0e21408c07585b9618140a3683d1903607f81f
Parents: db76923
Author: rpopma <rp...@apache.org>
Authored: Tue Mar 8 23:08:15 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Tue Mar 8 23:08:15 2016 +1100

----------------------------------------------------------------------
 .../log4j/message/ParameterFormatterTest.java   | 129 +++++++++++++++++++
 1 file changed, 129 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/8b0e2140/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
new file mode 100644
index 0000000..4158b17
--- /dev/null
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+import java.util.ArrayList;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Objects;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests ParameterFormatter.
+ */
+public class ParameterFormatterTest {
+
+    @Test
+    public void testCountArgumentPlaceholders() throws Exception {
+        assertEquals(0, ParameterFormatter.countArgumentPlaceholders(""));
+        assertEquals(0, ParameterFormatter.countArgumentPlaceholders("aaa"));
+        assertEquals(0, ParameterFormatter.countArgumentPlaceholders("\\{}"));
+        assertEquals(1, ParameterFormatter.countArgumentPlaceholders("{}"));
+        assertEquals(1, ParameterFormatter.countArgumentPlaceholders("{}\\{}"));
+        assertEquals(2, ParameterFormatter.countArgumentPlaceholders("{}{}"));
+        assertEquals(3, ParameterFormatter.countArgumentPlaceholders("{}{}{}"));
+        assertEquals(4, ParameterFormatter.countArgumentPlaceholders("{}{}{}aa{}"));
+        assertEquals(4, ParameterFormatter.countArgumentPlaceholders("{}{}{}a{]b{}"));
+        assertEquals(5, ParameterFormatter.countArgumentPlaceholders("{}{}{}a{}b{}"));
+    }
+
+    @Test
+    public void testFormat3StringArgs() {
+        final String testMsg = "Test message {}{} {}";
+        final String[] args = { "a", "b", "c" };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message ab c", result);
+    }
+
+    @Test
+    public void testFormatNullArgs() {
+        final String testMsg = "Test message {} {} {} {} {} {}";
+        final String[] args = { "a", null, "c", null, null, null };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message a null c null null null", result);
+    }
+
+    @Test
+    public void testFormatStringArgsIgnoresSuperfluousArgs() {
+        final String testMsg = "Test message {}{} {}";
+        final String[] args = { "a", "b", "c", "unnecessary", "superfluous" };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message ab c", result);
+    }
+
+    @Test
+    public void testFormatStringArgsWithEscape() {
+        final String testMsg = "Test message \\{}{} {}";
+        final String[] args = { "a", "b", "c" };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message {}a b", result);
+    }
+
+    @Test
+    public void testFormatStringArgsWithTrailingEscape() {
+        final String testMsg = "Test message {}{} {}\\";
+        final String[] args = { "a", "b", "c" };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message ab c\\", result);
+    }
+
+    @Test
+    public void testFormatStringArgsWithTrailingEscapedEscape() {
+        final String testMsg = "Test message {}{} {}\\\\";
+        final String[] args = { "a", "b", "c" };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message ab c\\\\", result);
+    }
+
+    @Test
+    public void testFormatStringArgsWithEscapedEscape() {
+        final String testMsg = "Test message \\\\{}{} {}";
+        final String[] args = { "a", "b", "c" };
+        final String result = ParameterFormatter.format(testMsg, args);
+        assertEquals("Test message \\ab c", result);
+    }
+
+    @Test
+    public void testFormatMessage() throws Exception {
+
+    }
+
+    @Test
+    public void testDeepToString() throws Exception {
+        List<Object> list = new ArrayList<>();
+        list.add(1);
+        list.add(list);
+        list.add(2);
+        String actual = ParameterFormatter.deepToString(list);
+        String expected = "[1, [..." + ParameterFormatter.identityToString(list) + "...], 2]";
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testIdentityToString() throws Exception {
+        List<Object> list = new ArrayList<>();
+        list.add(1);
+        list.add(list);
+        list.add(2);
+        String actual = ParameterFormatter.identityToString(list);
+        String expected = list.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(list));
+        assertEquals(expected, actual);
+    }
+}
\ No newline at end of file


[02/10] logging-log4j2 git commit: LOG4J2-1296 added additional unit tests for ParameterFormatter

Posted by mi...@apache.org.
LOG4J2-1296 added additional unit tests for ParameterFormatter


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

Branch: refs/heads/gelf-layout-gc-free
Commit: f157cc2ff083753356881254c518467062ea4b36
Parents: 8b0e214
Author: rpopma <rp...@apache.org>
Authored: Tue Mar 8 23:17:38 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Tue Mar 8 23:17:38 2016 +1100

----------------------------------------------------------------------
 .../log4j/message/ParameterFormatterTest.java   | 68 +++++++++++++++++++-
 1 file changed, 66 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f157cc2f/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
index 4158b17..e6a0dbd 100644
--- a/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/message/ParameterFormatterTest.java
@@ -17,7 +17,6 @@
 package org.apache.logging.log4j.message;
 
 import java.util.ArrayList;
-import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Objects;
 
@@ -101,8 +100,73 @@ public class ParameterFormatterTest {
     }
 
     @Test
-    public void testFormatMessage() throws Exception {
+    public void testFormatMessage3StringArgs() {
+        final String testMsg = "Test message {}{} {}";
+        final String[] args = { "a", "b", "c" };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 3);
+        final String result = sb.toString();
+        assertEquals("Test message ab c", result);
+    }
+
+    @Test
+    public void testFormatMessageNullArgs() {
+        final String testMsg = "Test message {} {} {} {} {} {}";
+        final String[] args = { "a", null, "c", null, null, null };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 6);
+        final String result = sb.toString();
+        assertEquals("Test message a null c null null null", result);
+    }
+
+    @Test
+    public void testFormatMessageStringArgsIgnoresSuperfluousArgs() {
+        final String testMsg = "Test message {}{} {}";
+        final String[] args = { "a", "b", "c", "unnecessary", "superfluous" };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 5);
+        final String result = sb.toString();
+        assertEquals("Test message ab c", result);
+    }
+
+    @Test
+    public void testFormatMessageStringArgsWithEscape() {
+        final String testMsg = "Test message \\{}{} {}";
+        final String[] args = { "a", "b", "c" };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 3);
+        final String result = sb.toString();
+        assertEquals("Test message {}a b", result);
+    }
+
+    @Test
+    public void testFormatMessageStringArgsWithTrailingEscape() {
+        final String testMsg = "Test message {}{} {}\\";
+        final String[] args = { "a", "b", "c" };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 3);
+        final String result = sb.toString();
+        assertEquals("Test message ab c\\", result);
+    }
 
+    @Test
+    public void testFormatMessageStringArgsWithTrailingEscapedEscape() {
+        final String testMsg = "Test message {}{} {}\\\\";
+        final String[] args = { "a", "b", "c" };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 3);
+        final String result = sb.toString();
+        assertEquals("Test message ab c\\\\", result);
+    }
+
+    @Test
+    public void testFormatMessageStringArgsWithEscapedEscape() {
+        final String testMsg = "Test message \\\\{}{} {}";
+        final String[] args = { "a", "b", "c" };
+        final StringBuilder sb = new StringBuilder();
+        ParameterFormatter.formatMessage(sb, testMsg, args, 3);
+        final String result = sb.toString();
+        assertEquals("Test message \\ab c", result);
     }
 
     @Test


[08/10] logging-log4j2 git commit: LOG4J2-1296 SmtpManager: when storing a Log4jLogEvent in a buffer, ensure that the Message is immutable

Posted by mi...@apache.org.
LOG4J2-1296 SmtpManager: when storing a Log4jLogEvent in a buffer, ensure that the Message is immutable


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

Branch: refs/heads/gelf-layout-gc-free
Commit: f1e50638916325f52b0860583e68e79f62b3601a
Parents: e039c72
Author: rpopma <rp...@apache.org>
Authored: Wed Mar 9 01:39:38 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Wed Mar 9 01:39:38 2016 +1100

----------------------------------------------------------------------
 .../java/org/apache/logging/log4j/core/net/SmtpManager.java   | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f1e50638/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 54bbc93..b101b2d 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,11 +42,13 @@ 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.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.layout.AbstractStringLayout.Serializer;
 import org.apache.logging.log4j.core.layout.PatternLayout;
 import org.apache.logging.log4j.core.util.CyclicBuffer;
 import org.apache.logging.log4j.core.util.NameUtil;
 import org.apache.logging.log4j.core.util.NetUtils;
+import org.apache.logging.log4j.message.ReusableMessage;
 import org.apache.logging.log4j.util.PropertiesUtil;
 import org.apache.logging.log4j.util.Strings;
 
@@ -57,7 +59,7 @@ public class SmtpManager extends AbstractManager {
     private static final SMTPManagerFactory FACTORY = new SMTPManagerFactory();
 
     private final Session session;
-    
+
     private final CyclicBuffer<LogEvent> buffer;
 
     private volatile MimeMessage message;
@@ -82,6 +84,9 @@ public class SmtpManager extends AbstractManager {
     }
 
     public void add(final LogEvent event) {
+        if (event instanceof Log4jLogEvent && event.getMessage() instanceof ReusableMessage) {
+            ((Log4jLogEvent) event).makeMessageImmutable();
+        }
         buffer.add(event);
     }
 


[06/10] logging-log4j2 git commit: LOG4J2-1296 initial unit tests for ReusableParameterizedMessage

Posted by mi...@apache.org.
LOG4J2-1296 initial unit tests for ReusableParameterizedMessage


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

Branch: refs/heads/gelf-layout-gc-free
Commit: 48b2da401182a1dc3d5ab436cc2d78bbd9dd738b
Parents: 34f8538
Author: rpopma <rp...@apache.org>
Authored: Wed Mar 9 01:04:50 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Wed Mar 9 01:04:50 2016 +1100

----------------------------------------------------------------------
 .../ReusableParameterizedMessageTest.java       | 59 ++++++++++++++++++++
 1 file changed, 59 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/48b2da40/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
new file mode 100644
index 0000000..abd396e
--- /dev/null
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/message/ReusableParameterizedMessageTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+import org.apache.logging.log4j.junit.Mutable;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests ReusableParameterizedMessage.
+ */
+public class ReusableParameterizedMessageTest {
+
+    @Test
+    public void testNoArgs() {
+        final String testMsg = "Test message {}";
+        ReusableParameterizedMessage msg = new ReusableParameterizedMessage();
+        msg.set(testMsg, null);
+        String result = msg.getFormattedMessage();
+        assertEquals(testMsg, result);
+
+        msg.set(testMsg, null, null);
+        result = msg.getFormattedMessage();
+        assertEquals("Test message null", result);
+    }
+
+    @Test
+    public void testNotSafeWithMutableParams() {
+        final String testMsg = "Test message {}";
+        final Mutable param = new Mutable().set("abc");
+        final ReusableParameterizedMessage msg = new ReusableParameterizedMessage();
+        msg.set(testMsg, param);
+
+        // modify parameter before calling msg.getFormattedMessage
+        param.set("XYZ");
+        final String actual = msg.getFormattedMessage();
+        assertEquals("Should use current param value", "Test message XYZ", actual);
+
+        // modify parameter after calling msg.getFormattedMessage
+        param.set("000");
+        final String after = msg.getFormattedMessage();
+        assertEquals("Renders again", "Test message 000", after);
+    }
+}


[04/10] logging-log4j2 git commit: LOG4J2-1296 creating a memento of RingBufferLogEvent should return an immutable Message, not a reusable/mutable Message

Posted by mi...@apache.org.
LOG4J2-1296 creating a memento of RingBufferLogEvent should return an immutable Message, not a reusable/mutable Message


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

Branch: refs/heads/gelf-layout-gc-free
Commit: d2634e4a932554d6174e6fac7e4d169f5904f53d
Parents: 98ded70
Author: rpopma <rp...@apache.org>
Authored: Wed Mar 9 01:00:53 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Wed Mar 9 01:00:53 2016 +1100

----------------------------------------------------------------------
 .../apache/logging/log4j/core/async/RingBufferLogEvent.java    | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d2634e4a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index a78582f..e918500 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -225,6 +225,10 @@ public class RingBufferLogEvent implements LogEvent {
         return message;
     }
 
+    private Message getNonNullImmutableMessage() {
+        return message != null ? message : new SimpleMessage(String.valueOf(messageText));
+    }
+
     @Override
     public Throwable getThrown() {
         // after deserialization, thrown is null but thrownProxy may be non-null
@@ -364,7 +368,7 @@ public class RingBufferLogEvent implements LogEvent {
                 .setLoggerFqcn(fqcn) //
                 .setLoggerName(loggerName) //
                 .setMarker(marker) //
-                .setMessage(getMessage()) // ensure non-null
+                .setMessage(getNonNullImmutableMessage()) // ensure non-null & immutable
                 .setNanoTime(nanoTime) //
                 .setSource(location) //
                 .setThreadId(threadId) //


[05/10] logging-log4j2 git commit: LOG4J2-1296 when passing a Log4jLogEvent to another thread (AsyncAppender or AsyncLoggerDisruptor), ensure that the Message is immutable

Posted by mi...@apache.org.
LOG4J2-1296 when passing a Log4jLogEvent to another thread (AsyncAppender or AsyncLoggerDisruptor), ensure that the Message is immutable


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

Branch: refs/heads/gelf-layout-gc-free
Commit: 34f8538da67aaf413bad59c13fd82e05f26c9924
Parents: d2634e4
Author: rpopma <rp...@apache.org>
Authored: Wed Mar 9 01:03:54 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Wed Mar 9 01:03:54 2016 +1100

----------------------------------------------------------------------
 .../core/async/AsyncLoggerConfigDisruptor.java      |  6 +++++-
 .../logging/log4j/core/impl/Log4jLogEvent.java      | 16 ++++++++++++++--
 2 files changed, 19 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/34f8538d/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
index 257e89a..f536d79 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLoggerConfigDisruptor.java
@@ -23,8 +23,10 @@ import java.util.concurrent.ThreadFactory;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Logger;
 import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.Log4jLogEvent;
 import org.apache.logging.log4j.core.jmx.RingBufferAdmin;
 import org.apache.logging.log4j.core.util.Constants;
+import org.apache.logging.log4j.message.ReusableMessage;
 import org.apache.logging.log4j.status.StatusLogger;
 
 import com.lmax.disruptor.EventFactory;
@@ -264,7 +266,9 @@ public class AsyncLoggerConfigDisruptor implements AsyncLoggerConfigDelegate {
 
     private LogEvent prepareEvent(final LogEvent event) {
         final LogEvent logEvent = ensureImmutable(event);
-        if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND) { // LOG4J2-898: user may choose
+        if (logEvent instanceof Log4jLogEvent && logEvent.getMessage() instanceof ReusableMessage) {
+            ((Log4jLogEvent) logEvent).makeMessageImmutable();
+        } else if (!Constants.FORMAT_MESSAGES_IN_BACKGROUND) { // LOG4J2-898: user may choose
             logEvent.getMessage().getFormattedMessage(); // LOG4J2-763: ask message to freeze parameters
         }
         return logEvent;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/34f8538d/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
index d8ff470..3f8961a 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
@@ -38,6 +38,8 @@ import org.apache.logging.log4j.core.util.DummyNanoClock;
 import org.apache.logging.log4j.core.util.NanoClock;
 import org.apache.logging.log4j.message.LoggerNameAwareMessage;
 import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.message.ReusableMessage;
+import org.apache.logging.log4j.message.SimpleMessage;
 import org.apache.logging.log4j.message.TimestampMessage;
 import org.apache.logging.log4j.status.StatusLogger;
 import org.apache.logging.log4j.util.Strings;
@@ -54,7 +56,7 @@ public class Log4jLogEvent implements LogEvent {
     private final Marker marker;
     private final Level level;
     private final String loggerName;
-    private final Message message;
+    private Message message;
     private final long timeMillis;
     private final transient Throwable thrown;
     private ThrowableProxy thrownProxy;
@@ -465,6 +467,10 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
         return message;
     }
 
+    public void makeMessageImmutable() {
+        message = new SimpleMessage(message.getFormattedMessage());
+    }
+
     @Override
     public long getThreadId() {
         if (threadId == 0) {
@@ -789,7 +795,9 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
             this.marker = event.marker;
             this.level = event.level;
             this.loggerName = event.loggerName;
-            this.message = event.message;
+            this.message = event.message instanceof ReusableMessage
+                    ? memento((ReusableMessage) event.message)
+                    : event.message;
             this.timeMillis = event.timeMillis;
             this.thrown = event.thrown;
             this.thrownProxy = event.thrownProxy;
@@ -804,6 +812,10 @@ public Log4jLogEvent(final String loggerName, final Marker marker, final String
             this.nanoTime = event.nanoTime;
         }
 
+        private Message memento(final ReusableMessage message) {
+            return new SimpleMessage(message.getFormattedMessage());
+        }
+
         /**
          * Returns a Log4jLogEvent using the data in the proxy.
          * @return Log4jLogEvent.


[07/10] logging-log4j2 git commit: LOG4J2-1291 added unit tests for PatternLayout.encode(LogEvent, ByteBufferDestination)

Posted by mi...@apache.org.
LOG4J2-1291 added unit tests for PatternLayout.encode(LogEvent, ByteBufferDestination)


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

Branch: refs/heads/gelf-layout-gc-free
Commit: e039c72c8cdb7b16ed6c25d45a35ae6d92a1d495
Parents: 48b2da4
Author: rpopma <rp...@apache.org>
Authored: Wed Mar 9 01:22:41 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Wed Mar 9 01:22:41 2016 +1100

----------------------------------------------------------------------
 .../log4j/core/layout/PatternLayoutTest.java    | 67 +++++++++++++++-----
 1 file changed, 51 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/e039c72c/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
index c4e9987..2184599 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/layout/PatternLayoutTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.layout;
 
+import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 
@@ -74,6 +75,32 @@ public class PatternLayoutTest {
         ThreadContext.clearMap();
     }
 
+    private static class Destination implements ByteBufferDestination {
+        ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[2048]);
+        @Override
+        public ByteBuffer getByteBuffer() {
+            return byteBuffer;
+        }
+
+        @Override
+        public ByteBuffer drain(final ByteBuffer buf) {
+            throw new IllegalStateException("Unexpected message larger than 2048 bytes");
+        }
+    }
+
+    private void assertToByteArray(final String expectedStr, final PatternLayout layout, final LogEvent event) {
+        final byte[] result = layout.toByteArray(event);
+        assertEquals(expectedStr, new String(result));
+    }
+
+    private void assertEncode(final String expectedStr, final PatternLayout layout, final LogEvent event) {
+        final Destination destination = new Destination();
+        layout.encode(event, destination);
+        final ByteBuffer byteBuffer = destination.getByteBuffer();
+        byteBuffer.flip(); // set limit to position, position back to zero
+        assertEquals(expectedStr, new String(byteBuffer.array(), 0, byteBuffer.limit()));
+    }
+
     @Test
     public void testEqualsEmptyMarker() throws Exception {
         // replace "[]" with the empty string
@@ -85,15 +112,17 @@ public class PatternLayoutTest {
                 .setLevel(Level.INFO) //
                 .setMarker(MarkerManager.getMarker("TestMarker")) //
                 .setMessage(new SimpleMessage("Hello, world!")).build();
-        final byte[] result1 = layout.toByteArray(event1);
-        assertEquals("[org.apache.logging.log4j.core.layout.PatternLayoutTest][TestMarker] Hello, world!", new String(result1));
+        assertToByteArray("[org.apache.logging.log4j.core.layout.PatternLayoutTest][TestMarker] Hello, world!", layout,
+                event1);
+        assertEncode("[org.apache.logging.log4j.core.layout.PatternLayoutTest][TestMarker] Hello, world!", layout,
+                event1);
         // empty marker
         final LogEvent event2 = Log4jLogEvent.newBuilder() //
                 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
                 .setLevel(Level.INFO) //
                 .setMessage(new SimpleMessage("Hello, world!")).build();
-        final byte[] result2 = layout.toByteArray(event2);
-        assertEquals("[org.apache.logging.log4j.core.layout.PatternLayoutTest] Hello, world!", new String(result2));
+        assertToByteArray("[org.apache.logging.log4j.core.layout.PatternLayoutTest] Hello, world!", layout, event2);
+        assertEncode("[org.apache.logging.log4j.core.layout.PatternLayoutTest] Hello, world!", layout, event2);
     }
 
     @Test
@@ -167,8 +196,8 @@ public class PatternLayoutTest {
                 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
                 .setLevel(Level.INFO) //
                 .setMessage(new SimpleMessage("Hello")).build();
-        final byte[] result = layout.toByteArray(event);
-        assertEquals(expectedStr, new String(result));
+        assertToByteArray(expectedStr, layout, event);
+        assertEncode(expectedStr, layout, event);
     }
 
     @Test
@@ -210,7 +239,7 @@ public class PatternLayoutTest {
                 .setIncludeLocation(true)
                 .setMessage(new SimpleMessage("entry")).build();
         final String result1 = new FauxLogger().formatEvent(event1, layout);
-        final String expectSuffix1 = String.format("====== PatternLayoutTest.testPatternSelector:212 entry ======%n");
+        final String expectSuffix1 = String.format("====== PatternLayoutTest.testPatternSelector:241 entry ======%n");
         assertTrue("Unexpected result: " + result1, result1.endsWith(expectSuffix1));
         final LogEvent event2 = Log4jLogEvent.newBuilder() //
                 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
@@ -229,8 +258,8 @@ public class PatternLayoutTest {
                 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
                 .setLevel(Level.INFO) //
                 .setMessage(new SimpleMessage("Hello, world!")).build();
-        final byte[] result = layout.toByteArray(event);
-        assertEquals("org/apache/logging/log4j/core/layout/PatternLayoutTest Hello, world!", new String(result));
+        assertToByteArray("org/apache/logging/log4j/core/layout/PatternLayoutTest Hello, world!", layout, event);
+        assertEncode("org/apache/logging/log4j/core/layout/PatternLayoutTest Hello, world!", layout, event);
     }
 
     @Test
@@ -244,15 +273,18 @@ public class PatternLayoutTest {
                 .setLevel(Level.INFO) //
                 .setMarker(MarkerManager.getMarker("TestMarker")) //
                 .setMessage(new SimpleMessage("Hello, world!")).build();
-        final byte[] result1 = layout.toByteArray(event1);
-        assertEquals("[org.apache.logging.log4j.core.layout.PatternLayoutTest][TestMarker] Hello, world!", new String(result1));
+        assertToByteArray("[org.apache.logging.log4j.core.layout.PatternLayoutTest][TestMarker] Hello, world!", layout,
+                event1);
+        assertEncode("[org.apache.logging.log4j.core.layout.PatternLayoutTest][TestMarker] Hello, world!", layout,
+                event1);
+
         // empty marker
         final LogEvent event2 = Log4jLogEvent.newBuilder() //
                 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
                 .setLevel(Level.INFO) //
                 .setMessage(new SimpleMessage("Hello, world!")).build();
-        final byte[] result2 = layout.toByteArray(event2);
-        assertEquals("[org.apache.logging.log4j.core.layout.PatternLayoutTest] Hello, world!", new String(result2));
+        assertToByteArray("[org.apache.logging.log4j.core.layout.PatternLayoutTest] Hello, world!", layout, event2);
+        assertEncode("[org.apache.logging.log4j.core.layout.PatternLayoutTest] Hello, world!", layout, event2);
     }
 
     @Test
@@ -263,9 +295,12 @@ public class PatternLayoutTest {
                 .setLoggerName(this.getClass().getName()).setLoggerFqcn("org.apache.logging.log4j.core.Logger") //
                 .setLevel(Level.INFO) //
                 .setMessage(new SimpleMessage("Hello, world!")).build();
-        final byte[] result = layout.toByteArray(event);
-        assertEquals("\\INFO\tHello, world!\n\torg.apache.logging.log4j.core.layout.PatternLayoutTest\r\n\f",
-                new String(result));
+        assertToByteArray("\\INFO\tHello, world!\n" +
+                "\torg.apache.logging.log4j.core.layout.PatternLayoutTest\r\n" +
+                "\f", layout, event);
+        assertEncode("\\INFO\tHello, world!\n" +
+                "\torg.apache.logging.log4j.core.layout.PatternLayoutTest\r\n" +
+                "\f", layout, event);
     }
 
     @Test


Re: [10/10] logging-log4j2 git commit: Unit test for GelfLayout.encode

Posted by Mikael Ståldal <mi...@magine.com>.
Thanks, fixed now.

On Tue, Mar 8, 2016 at 10:13 PM, Remko Popma <re...@gmail.com> wrote:

>
>
> On Wed, Mar 9, 2016 at 3:35 AM, <mi...@apache.org> wrote:
>
>> Unit test for GelfLayout.encode
>>
>>
>> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
>> Commit:
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/58152b79
>> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/58152b79
>> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/58152b79
>>
>> Branch: refs/heads/gelf-layout-gc-free
>> Commit: 58152b79b0c883ba6df57b06bbb4e2c96353232e
>> Parents: 7467e5d
>> Author: Mikael Ståldal <mi...@magine.com>
>> Authored: Tue Mar 8 17:34:43 2016 +0100
>> Committer: Mikael Ståldal <mi...@magine.com>
>> Committed: Tue Mar 8 17:34:43 2016 +0100
>>
>> ----------------------------------------------------------------------
>>  .../log4j/core/layout/GelfLayoutTest.java       | 75 +++++++++++---------
>>  .../test/appender/EncodingListAppender.java     | 64 +++++++++++++++++
>>  .../log4j/test/appender/ListAppender.java       |  9 ++-
>>  3 files changed, 112 insertions(+), 36 deletions(-)
>> ----------------------------------------------------------------------
>>
>>
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/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 2aa7eda..c82fa21 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
>> @@ -16,32 +16,28 @@
>>   */
>>  package org.apache.logging.log4j.core.layout;
>>
>> -import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
>> -
>> -import java.io.ByteArrayInputStream;
>> -import java.io.IOException;
>> -import java.io.InputStream;
>> -import java.util.List;
>> -import java.util.zip.GZIPInputStream;
>> -import java.util.zip.InflaterInputStream;
>> -
>> +import com.fasterxml.jackson.core.io.JsonStringEncoder;
>>  import org.apache.commons.io.IOUtils;
>>  import org.apache.logging.log4j.Level;
>>  import org.apache.logging.log4j.ThreadContext;
>> -import org.apache.logging.log4j.core.Appender;
>> -import org.apache.logging.log4j.core.BasicConfigurationFactory;
>> -import org.apache.logging.log4j.core.LogEvent;
>> -import org.apache.logging.log4j.core.Logger;
>> -import org.apache.logging.log4j.core.LoggerContext;
>> +import org.apache.logging.log4j.core.*;
>>  import org.apache.logging.log4j.core.config.ConfigurationFactory;
>>  import org.apache.logging.log4j.core.layout.GelfLayout.CompressionType;
>>  import org.apache.logging.log4j.core.util.KeyValuePair;
>> +import org.apache.logging.log4j.test.appender.EncodingListAppender;
>>  import org.apache.logging.log4j.test.appender.ListAppender;
>>  import org.junit.AfterClass;
>>  import org.junit.BeforeClass;
>>  import org.junit.Test;
>>
>> -import com.fasterxml.jackson.core.io.JsonStringEncoder;
>> +import java.io.ByteArrayInputStream;
>> +import java.io.IOException;
>> +import java.io.InputStream;
>> +import java.util.List;
>> +import java.util.zip.GZIPInputStream;
>> +import java.util.zip.InflaterInputStream;
>> +
>> +import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
>>
>>  public class GelfLayoutTest {
>>      static ConfigurationFactory configFactory = new
>> BasicConfigurationFactory();
>> @@ -85,18 +81,20 @@ public class GelfLayoutTest {
>>          final GelfLayout layout = GelfLayout.createLayout(HOSTNAME, new
>> KeyValuePair[] {
>>                  new KeyValuePair(KEY1, VALUE1),
>>                  new KeyValuePair(KEY2, VALUE2), }, compressionType,
>> 1024);
>> -        // ConsoleAppender appender = new ConsoleAppender("Console",
>> layout);
>>          final ListAppender eventAppender = new ListAppender("Events",
>> null, null, true, false);
>>          final ListAppender rawAppender = new ListAppender("Raw", null,
>> layout, true, true);
>>          final ListAppender formattedAppender = new
>> ListAppender("Formatted", null, layout, true, false);
>> +        final EncodingListAppender encodedAppender = new
>> EncodingListAppender("Encoded", null, layout, false, true);
>>          eventAppender.start();
>>          rawAppender.start();
>>          formattedAppender.start();
>> +        encodedAppender.start();
>>
>>          // set appenders on root and set level to debug
>>          root.addAppender(eventAppender);
>>          root.addAppender(rawAppender);
>>          root.addAppender(formattedAppender);
>> +        root.addAppender(encodedAppender);
>>          root.setLevel(Level.DEBUG);
>>
>>          root.debug(LINE1);
>> @@ -116,6 +114,7 @@ public class GelfLayoutTest {
>>          final List<LogEvent> events = eventAppender.getEvents();
>>          final List<byte[]> raw = rawAppender.getData();
>>          final List<String> messages = formattedAppender.getMessages();
>> +        final List<byte[]> raw2 = encodedAppender.getData();
>>          final String threadName = Thread.currentThread().getName();
>>
>>          //@formatter:off
>> @@ -148,42 +147,52 @@ public class GelfLayoutTest {
>>                  messages.get(1));
>>          //@formatter:on
>>          final byte[] compressed = raw.get(2);
>> +        final byte[] compressed2 = raw2.get(2);
>>          final ByteArrayInputStream bais = new
>> ByteArrayInputStream(compressed);
>> -        InputStream inflaterStream = null;
>> +        final ByteArrayInputStream bais2 = new
>> ByteArrayInputStream(compressed2);
>> +        InputStream inflaterStream;
>> +        InputStream inflaterStream2;
>>          switch (compressionType) {
>>          case GZIP:
>>              inflaterStream = new GZIPInputStream(bais);
>> +            inflaterStream2 = new GZIPInputStream(bais2);
>>              break;
>>          case ZLIB:
>>              inflaterStream = new InflaterInputStream(bais);
>> +            inflaterStream2 = new InflaterInputStream(bais2);
>>              break;
>>          case OFF:
>>              inflaterStream = bais;
>> +            inflaterStream2 = bais2;
>>              break;
>>          default:
>>              throw new IllegalStateException("Missing test case clause");
>>          }
>>          final byte[] uncompressed = IOUtils.toByteArray(inflaterStream);
>> +        final byte[] uncompressed2 =
>> IOUtils.toByteArray(inflaterStream2);
>>          inflaterStream.close();
>> +        inflaterStream2.close();
>>          final String uncompressedString = new String(uncompressed,
>> layout.getCharset());
>> +        final String uncompressedString2 = new String(uncompressed2,
>> layout.getCharset());
>>          //@formatter:off
>> -        assertJsonEquals("{" +
>> -                        "\"version\": \"1.1\"," +
>> -                        "\"host\": \"" + HOSTNAME + "\"," +
>> -                        "\"timestamp\": " +
>> GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
>> -                        "\"level\": 3," +
>> -                        "\"_thread\": \"" + threadName + "\"," +
>> -                        "\"_logger\": \"\"," +
>> -                        "\"short_message\": \"" + LINE3 + "\"," +
>> -                        "\"full_message\": \"" +
>> String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
>> -                                GelfLayout.formatThrowable(exception)))
>> + "\"," +
>> -                        "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
>> -                        "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
>> -                        "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
>> -                        "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
>> -                        "}",
>> -                uncompressedString);
>> +        String expected = "{" +
>> +                "\"version\": \"1.1\"," +
>> +                "\"host\": \"" + HOSTNAME + "\"," +
>> +                "\"timestamp\": " +
>> GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
>> +                "\"level\": 3," +
>> +                "\"_thread\": \"" + threadName + "\"," +
>> +                "\"_logger\": \"\"," +
>> +                "\"short_message\": \"" + LINE3 + "\"," +
>> +                "\"full_message\": \"" +
>> String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
>> +                GelfLayout.formatThrowable(exception))) + "\"," +
>> +                "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
>> +                "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
>> +                "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
>> +                "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
>> +                "}";
>>          //@formatter:on
>> +        assertJsonEquals(expected, uncompressedString);
>> +        assertJsonEquals(expected, uncompressedString2);
>>      }
>>
>>      @Test
>>
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
>> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
>> new file mode 100644
>> index 0000000..810e18f
>> --- /dev/null
>> +++
>> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
>> @@ -0,0 +1,64 @@
>> +package org.apache.logging.log4j.test.appender;
>> +
>> +import org.apache.logging.log4j.core.Filter;
>> +import org.apache.logging.log4j.core.Layout;
>> +import org.apache.logging.log4j.core.LogEvent;
>> +import org.apache.logging.log4j.core.layout.ByteBufferDestination;
>> +import org.apache.logging.log4j.core.layout.SerializedLayout;
>> +
>> +import java.io.Serializable;
>> +import java.nio.ByteBuffer;
>> +
>> +/**
>> + * This appender is primarily used for testing. Use in a real
>> environment is discouraged as the
>> + * List could eventually grow to cause an OutOfMemoryError.
>> + *
>> + * This appender will use {@link Layout#encode(Object,
>> ByteBufferDestination)} (and not {@link Layout#toByteArray(LogEvent)}).
>> + */
>> +public class EncodingListAppender extends ListAppender {
>> +
>> +    public EncodingListAppender(String name) {
>> +        super(name);
>> +    }
>> +
>> +    public EncodingListAppender(String name, Filter filter, Layout<?
>> extends Serializable> layout, boolean newline, boolean raw) {
>> +        super(name, filter, layout, newline, raw);
>> +    }
>> +
>> +    private class Destination implements ByteBufferDestination {
>> +        ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4096]);
>> +        @Override
>> +        public ByteBuffer getByteBuffer() {
>> +            return byteBuffer;
>> +        }
>> +
>> +        @Override
>> +        public ByteBuffer drain(final ByteBuffer buf) {
>> +            throw new IllegalStateException("Unexpected message larger
>> than 4096 bytes");
>> +        }
>> +    }
>> +
>> +    @Override
>> +    public synchronized void append(final LogEvent event) {
>> +        final Layout<? extends Serializable> layout = getLayout();
>> +        if (layout == null) {
>> +            events.add(event);
>> +        } else if (layout instanceof SerializedLayout) {
>> +            Destination content = new Destination();
>> +            content.byteBuffer.put(layout.getHeader());
>> +            layout.encode(event, content);
>> +            content.getByteBuffer().rewind();
>> +            byte[] record = new
>> byte[content.getByteBuffer().remaining()];
>> +            content.getByteBuffer().get(record);
>> +            data.add(record);
>>
> I think there is a bug here. ByteBuffer.rewind() does not change limit, it
> just sets the position back to zero. (Meaning you no longer know how many
> bytes were put into the buffer.) I believe you want to use
> ByteBuffer.flip() instead of rewind().
> If you use flip(), the limit is set to the current position before the
> position is reset to zero. After a flip(), the remaining() method will
> return the difference between the limit and the current position, which is
> what you want: the number of bytes you just wrote into the buffer.
>
>
>
>> +        } else {
>> +            Destination content = new Destination();
>> +            layout.encode(event, content);
>> +            content.getByteBuffer().rewind();
>> +            byte[] record = new
>> byte[content.getByteBuffer().remaining()];
>> +            content.getByteBuffer().get(record);
>> +            write(record);
>> +        }
>> +    }
>> +
>> +}
>>
>>
>> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
>> ----------------------------------------------------------------------
>> diff --git
>> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
>> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
>> index 05fa157..cd9ec82 100644
>> ---
>> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
>> +++
>> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
>> @@ -36,6 +36,9 @@ import
>> org.apache.logging.log4j.core.layout.SerializedLayout;
>>  /**
>>   * This appender is primarily used for testing. Use in a real
>> environment is discouraged as the
>>   * List could eventually grow to cause an OutOfMemoryError.
>> + *
>> + * This appender will use {@link Layout#toByteArray(LogEvent)}.
>> + *
>>   * @see
>> org.apache.logging.log4j.junit.LoggerContextRule#getListAppender(String)
>> ILC.getListAppender
>>   */
>>  @Plugin(name = "List", category = "Core", elementType = "appender",
>> printObject = true)
>> @@ -45,11 +48,11 @@ public class ListAppender extends AbstractAppender {
>>
>>      // Use CopyOnWriteArrayList?
>>
>> -    private final List<LogEvent> events = new ArrayList<>();
>> +    final List<LogEvent> events = new ArrayList<>();
>>
>>      private final List<String> messages = new ArrayList<>();
>>
>> -    private final List<byte[]> data = new ArrayList<>();
>> +    final List<byte[]> data = new ArrayList<>();
>>
>>      private final boolean newLine;
>>
>> @@ -93,7 +96,7 @@ public class ListAppender extends AbstractAppender {
>>          }
>>      }
>>
>> -    private void write(final byte[] bytes) {
>> +    void write(final byte[] bytes) {
>>          if (raw) {
>>              data.add(bytes);
>>              return;
>>
>>
>


-- 
[image: MagineTV]

*Mikael Ståldal*
Senior software developer

*Magine TV*
mikael.staldal@magine.com
Grev Turegatan 3  | 114 46 Stockholm, Sweden  |   www.magine.com

Privileged and/or Confidential Information may be contained in this
message. If you are not the addressee indicated in this message
(or responsible for delivery of the message to such a person), you may not
copy or deliver this message to anyone. In such case,
you should destroy this message and kindly notify the sender by reply
email.

Re: [10/10] logging-log4j2 git commit: Unit test for GelfLayout.encode

Posted by Remko Popma <re...@gmail.com>.
On Wed, Mar 9, 2016 at 3:35 AM, <mi...@apache.org> wrote:

> Unit test for GelfLayout.encode
>
>
> Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
> Commit:
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/58152b79
> Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/58152b79
> Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/58152b79
>
> Branch: refs/heads/gelf-layout-gc-free
> Commit: 58152b79b0c883ba6df57b06bbb4e2c96353232e
> Parents: 7467e5d
> Author: Mikael Ståldal <mi...@magine.com>
> Authored: Tue Mar 8 17:34:43 2016 +0100
> Committer: Mikael Ståldal <mi...@magine.com>
> Committed: Tue Mar 8 17:34:43 2016 +0100
>
> ----------------------------------------------------------------------
>  .../log4j/core/layout/GelfLayoutTest.java       | 75 +++++++++++---------
>  .../test/appender/EncodingListAppender.java     | 64 +++++++++++++++++
>  .../log4j/test/appender/ListAppender.java       |  9 ++-
>  3 files changed, 112 insertions(+), 36 deletions(-)
> ----------------------------------------------------------------------
>
>
>
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/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 2aa7eda..c82fa21 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
> @@ -16,32 +16,28 @@
>   */
>  package org.apache.logging.log4j.core.layout;
>
> -import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
> -
> -import java.io.ByteArrayInputStream;
> -import java.io.IOException;
> -import java.io.InputStream;
> -import java.util.List;
> -import java.util.zip.GZIPInputStream;
> -import java.util.zip.InflaterInputStream;
> -
> +import com.fasterxml.jackson.core.io.JsonStringEncoder;
>  import org.apache.commons.io.IOUtils;
>  import org.apache.logging.log4j.Level;
>  import org.apache.logging.log4j.ThreadContext;
> -import org.apache.logging.log4j.core.Appender;
> -import org.apache.logging.log4j.core.BasicConfigurationFactory;
> -import org.apache.logging.log4j.core.LogEvent;
> -import org.apache.logging.log4j.core.Logger;
> -import org.apache.logging.log4j.core.LoggerContext;
> +import org.apache.logging.log4j.core.*;
>  import org.apache.logging.log4j.core.config.ConfigurationFactory;
>  import org.apache.logging.log4j.core.layout.GelfLayout.CompressionType;
>  import org.apache.logging.log4j.core.util.KeyValuePair;
> +import org.apache.logging.log4j.test.appender.EncodingListAppender;
>  import org.apache.logging.log4j.test.appender.ListAppender;
>  import org.junit.AfterClass;
>  import org.junit.BeforeClass;
>  import org.junit.Test;
>
> -import com.fasterxml.jackson.core.io.JsonStringEncoder;
> +import java.io.ByteArrayInputStream;
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.util.List;
> +import java.util.zip.GZIPInputStream;
> +import java.util.zip.InflaterInputStream;
> +
> +import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
>
>  public class GelfLayoutTest {
>      static ConfigurationFactory configFactory = new
> BasicConfigurationFactory();
> @@ -85,18 +81,20 @@ public class GelfLayoutTest {
>          final GelfLayout layout = GelfLayout.createLayout(HOSTNAME, new
> KeyValuePair[] {
>                  new KeyValuePair(KEY1, VALUE1),
>                  new KeyValuePair(KEY2, VALUE2), }, compressionType, 1024);
> -        // ConsoleAppender appender = new ConsoleAppender("Console",
> layout);
>          final ListAppender eventAppender = new ListAppender("Events",
> null, null, true, false);
>          final ListAppender rawAppender = new ListAppender("Raw", null,
> layout, true, true);
>          final ListAppender formattedAppender = new
> ListAppender("Formatted", null, layout, true, false);
> +        final EncodingListAppender encodedAppender = new
> EncodingListAppender("Encoded", null, layout, false, true);
>          eventAppender.start();
>          rawAppender.start();
>          formattedAppender.start();
> +        encodedAppender.start();
>
>          // set appenders on root and set level to debug
>          root.addAppender(eventAppender);
>          root.addAppender(rawAppender);
>          root.addAppender(formattedAppender);
> +        root.addAppender(encodedAppender);
>          root.setLevel(Level.DEBUG);
>
>          root.debug(LINE1);
> @@ -116,6 +114,7 @@ public class GelfLayoutTest {
>          final List<LogEvent> events = eventAppender.getEvents();
>          final List<byte[]> raw = rawAppender.getData();
>          final List<String> messages = formattedAppender.getMessages();
> +        final List<byte[]> raw2 = encodedAppender.getData();
>          final String threadName = Thread.currentThread().getName();
>
>          //@formatter:off
> @@ -148,42 +147,52 @@ public class GelfLayoutTest {
>                  messages.get(1));
>          //@formatter:on
>          final byte[] compressed = raw.get(2);
> +        final byte[] compressed2 = raw2.get(2);
>          final ByteArrayInputStream bais = new
> ByteArrayInputStream(compressed);
> -        InputStream inflaterStream = null;
> +        final ByteArrayInputStream bais2 = new
> ByteArrayInputStream(compressed2);
> +        InputStream inflaterStream;
> +        InputStream inflaterStream2;
>          switch (compressionType) {
>          case GZIP:
>              inflaterStream = new GZIPInputStream(bais);
> +            inflaterStream2 = new GZIPInputStream(bais2);
>              break;
>          case ZLIB:
>              inflaterStream = new InflaterInputStream(bais);
> +            inflaterStream2 = new InflaterInputStream(bais2);
>              break;
>          case OFF:
>              inflaterStream = bais;
> +            inflaterStream2 = bais2;
>              break;
>          default:
>              throw new IllegalStateException("Missing test case clause");
>          }
>          final byte[] uncompressed = IOUtils.toByteArray(inflaterStream);
> +        final byte[] uncompressed2 = IOUtils.toByteArray(inflaterStream2);
>          inflaterStream.close();
> +        inflaterStream2.close();
>          final String uncompressedString = new String(uncompressed,
> layout.getCharset());
> +        final String uncompressedString2 = new String(uncompressed2,
> layout.getCharset());
>          //@formatter:off
> -        assertJsonEquals("{" +
> -                        "\"version\": \"1.1\"," +
> -                        "\"host\": \"" + HOSTNAME + "\"," +
> -                        "\"timestamp\": " +
> GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
> -                        "\"level\": 3," +
> -                        "\"_thread\": \"" + threadName + "\"," +
> -                        "\"_logger\": \"\"," +
> -                        "\"short_message\": \"" + LINE3 + "\"," +
> -                        "\"full_message\": \"" +
> String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
> -                                GelfLayout.formatThrowable(exception))) +
> "\"," +
> -                        "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
> -                        "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
> -                        "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
> -                        "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
> -                        "}",
> -                uncompressedString);
> +        String expected = "{" +
> +                "\"version\": \"1.1\"," +
> +                "\"host\": \"" + HOSTNAME + "\"," +
> +                "\"timestamp\": " +
> GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
> +                "\"level\": 3," +
> +                "\"_thread\": \"" + threadName + "\"," +
> +                "\"_logger\": \"\"," +
> +                "\"short_message\": \"" + LINE3 + "\"," +
> +                "\"full_message\": \"" +
> String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
> +                GelfLayout.formatThrowable(exception))) + "\"," +
> +                "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
> +                "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
> +                "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
> +                "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
> +                "}";
>          //@formatter:on
> +        assertJsonEquals(expected, uncompressedString);
> +        assertJsonEquals(expected, uncompressedString2);
>      }
>
>      @Test
>
>
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> ----------------------------------------------------------------------
> diff --git
> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> new file mode 100644
> index 0000000..810e18f
> --- /dev/null
> +++
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
> @@ -0,0 +1,64 @@
> +package org.apache.logging.log4j.test.appender;
> +
> +import org.apache.logging.log4j.core.Filter;
> +import org.apache.logging.log4j.core.Layout;
> +import org.apache.logging.log4j.core.LogEvent;
> +import org.apache.logging.log4j.core.layout.ByteBufferDestination;
> +import org.apache.logging.log4j.core.layout.SerializedLayout;
> +
> +import java.io.Serializable;
> +import java.nio.ByteBuffer;
> +
> +/**
> + * This appender is primarily used for testing. Use in a real environment
> is discouraged as the
> + * List could eventually grow to cause an OutOfMemoryError.
> + *
> + * This appender will use {@link Layout#encode(Object,
> ByteBufferDestination)} (and not {@link Layout#toByteArray(LogEvent)}).
> + */
> +public class EncodingListAppender extends ListAppender {
> +
> +    public EncodingListAppender(String name) {
> +        super(name);
> +    }
> +
> +    public EncodingListAppender(String name, Filter filter, Layout<?
> extends Serializable> layout, boolean newline, boolean raw) {
> +        super(name, filter, layout, newline, raw);
> +    }
> +
> +    private class Destination implements ByteBufferDestination {
> +        ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4096]);
> +        @Override
> +        public ByteBuffer getByteBuffer() {
> +            return byteBuffer;
> +        }
> +
> +        @Override
> +        public ByteBuffer drain(final ByteBuffer buf) {
> +            throw new IllegalStateException("Unexpected message larger
> than 4096 bytes");
> +        }
> +    }
> +
> +    @Override
> +    public synchronized void append(final LogEvent event) {
> +        final Layout<? extends Serializable> layout = getLayout();
> +        if (layout == null) {
> +            events.add(event);
> +        } else if (layout instanceof SerializedLayout) {
> +            Destination content = new Destination();
> +            content.byteBuffer.put(layout.getHeader());
> +            layout.encode(event, content);
> +            content.getByteBuffer().rewind();
> +            byte[] record = new byte[content.getByteBuffer().remaining()];
> +            content.getByteBuffer().get(record);
> +            data.add(record);
>
I think there is a bug here. ByteBuffer.rewind() does not change limit, it
just sets the position back to zero. (Meaning you no longer know how many
bytes were put into the buffer.) I believe you want to use
ByteBuffer.flip() instead of rewind().
If you use flip(), the limit is set to the current position before the
position is reset to zero. After a flip(), the remaining() method will
return the difference between the limit and the current position, which is
what you want: the number of bytes you just wrote into the buffer.



> +        } else {
> +            Destination content = new Destination();
> +            layout.encode(event, content);
> +            content.getByteBuffer().rewind();
> +            byte[] record = new byte[content.getByteBuffer().remaining()];
> +            content.getByteBuffer().get(record);
> +            write(record);
> +        }
> +    }
> +
> +}
>
>
> http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> ----------------------------------------------------------------------
> diff --git
> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> index 05fa157..cd9ec82 100644
> ---
> a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> +++
> b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
> @@ -36,6 +36,9 @@ import
> org.apache.logging.log4j.core.layout.SerializedLayout;
>  /**
>   * This appender is primarily used for testing. Use in a real environment
> is discouraged as the
>   * List could eventually grow to cause an OutOfMemoryError.
> + *
> + * This appender will use {@link Layout#toByteArray(LogEvent)}.
> + *
>   * @see
> org.apache.logging.log4j.junit.LoggerContextRule#getListAppender(String)
> ILC.getListAppender
>   */
>  @Plugin(name = "List", category = "Core", elementType = "appender",
> printObject = true)
> @@ -45,11 +48,11 @@ public class ListAppender extends AbstractAppender {
>
>      // Use CopyOnWriteArrayList?
>
> -    private final List<LogEvent> events = new ArrayList<>();
> +    final List<LogEvent> events = new ArrayList<>();
>
>      private final List<String> messages = new ArrayList<>();
>
> -    private final List<byte[]> data = new ArrayList<>();
> +    final List<byte[]> data = new ArrayList<>();
>
>      private final boolean newLine;
>
> @@ -93,7 +96,7 @@ public class ListAppender extends AbstractAppender {
>          }
>      }
>
> -    private void write(final byte[] bytes) {
> +    void write(final byte[] bytes) {
>          if (raw) {
>              data.add(bytes);
>              return;
>
>

[10/10] logging-log4j2 git commit: Unit test for GelfLayout.encode

Posted by mi...@apache.org.
Unit test for GelfLayout.encode


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

Branch: refs/heads/gelf-layout-gc-free
Commit: 58152b79b0c883ba6df57b06bbb4e2c96353232e
Parents: 7467e5d
Author: Mikael Ståldal <mi...@magine.com>
Authored: Tue Mar 8 17:34:43 2016 +0100
Committer: Mikael Ståldal <mi...@magine.com>
Committed: Tue Mar 8 17:34:43 2016 +0100

----------------------------------------------------------------------
 .../log4j/core/layout/GelfLayoutTest.java       | 75 +++++++++++---------
 .../test/appender/EncodingListAppender.java     | 64 +++++++++++++++++
 .../log4j/test/appender/ListAppender.java       |  9 ++-
 3 files changed, 112 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/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 2aa7eda..c82fa21 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
@@ -16,32 +16,28 @@
  */
 package org.apache.logging.log4j.core.layout;
 
-import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.InflaterInputStream;
-
+import com.fasterxml.jackson.core.io.JsonStringEncoder;
 import org.apache.commons.io.IOUtils;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.ThreadContext;
-import org.apache.logging.log4j.core.Appender;
-import org.apache.logging.log4j.core.BasicConfigurationFactory;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.Logger;
-import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.*;
 import org.apache.logging.log4j.core.config.ConfigurationFactory;
 import org.apache.logging.log4j.core.layout.GelfLayout.CompressionType;
 import org.apache.logging.log4j.core.util.KeyValuePair;
+import org.apache.logging.log4j.test.appender.EncodingListAppender;
 import org.apache.logging.log4j.test.appender.ListAppender;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
-import com.fasterxml.jackson.core.io.JsonStringEncoder;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+
+import static net.javacrumbs.jsonunit.JsonAssert.assertJsonEquals;
 
 public class GelfLayoutTest {
     static ConfigurationFactory configFactory = new BasicConfigurationFactory();
@@ -85,18 +81,20 @@ public class GelfLayoutTest {
         final GelfLayout layout = GelfLayout.createLayout(HOSTNAME, new KeyValuePair[] {
                 new KeyValuePair(KEY1, VALUE1),
                 new KeyValuePair(KEY2, VALUE2), }, compressionType, 1024);
-        // ConsoleAppender appender = new ConsoleAppender("Console", layout);
         final ListAppender eventAppender = new ListAppender("Events", null, null, true, false);
         final ListAppender rawAppender = new ListAppender("Raw", null, layout, true, true);
         final ListAppender formattedAppender = new ListAppender("Formatted", null, layout, true, false);
+        final EncodingListAppender encodedAppender = new EncodingListAppender("Encoded", null, layout, false, true);
         eventAppender.start();
         rawAppender.start();
         formattedAppender.start();
+        encodedAppender.start();
 
         // set appenders on root and set level to debug
         root.addAppender(eventAppender);
         root.addAppender(rawAppender);
         root.addAppender(formattedAppender);
+        root.addAppender(encodedAppender);
         root.setLevel(Level.DEBUG);
 
         root.debug(LINE1);
@@ -116,6 +114,7 @@ public class GelfLayoutTest {
         final List<LogEvent> events = eventAppender.getEvents();
         final List<byte[]> raw = rawAppender.getData();
         final List<String> messages = formattedAppender.getMessages();
+        final List<byte[]> raw2 = encodedAppender.getData();
         final String threadName = Thread.currentThread().getName();
 
         //@formatter:off
@@ -148,42 +147,52 @@ public class GelfLayoutTest {
                 messages.get(1));
         //@formatter:on
         final byte[] compressed = raw.get(2);
+        final byte[] compressed2 = raw2.get(2);
         final ByteArrayInputStream bais = new ByteArrayInputStream(compressed);
-        InputStream inflaterStream = null;
+        final ByteArrayInputStream bais2 = new ByteArrayInputStream(compressed2);
+        InputStream inflaterStream;
+        InputStream inflaterStream2;
         switch (compressionType) {
         case GZIP:
             inflaterStream = new GZIPInputStream(bais);
+            inflaterStream2 = new GZIPInputStream(bais2);
             break;
         case ZLIB:
             inflaterStream = new InflaterInputStream(bais);
+            inflaterStream2 = new InflaterInputStream(bais2);
             break;
         case OFF:
             inflaterStream = bais;
+            inflaterStream2 = bais2;
             break;
         default:
             throw new IllegalStateException("Missing test case clause");
         }
         final byte[] uncompressed = IOUtils.toByteArray(inflaterStream);
+        final byte[] uncompressed2 = IOUtils.toByteArray(inflaterStream2);
         inflaterStream.close();
+        inflaterStream2.close();
         final String uncompressedString = new String(uncompressed, layout.getCharset());
+        final String uncompressedString2 = new String(uncompressed2, layout.getCharset());
         //@formatter:off
-        assertJsonEquals("{" +
-                        "\"version\": \"1.1\"," +
-                        "\"host\": \"" + HOSTNAME + "\"," +
-                        "\"timestamp\": " + GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
-                        "\"level\": 3," +
-                        "\"_thread\": \"" + threadName + "\"," +
-                        "\"_logger\": \"\"," +
-                        "\"short_message\": \"" + LINE3 + "\"," +
-                        "\"full_message\": \"" + String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
-                                GelfLayout.formatThrowable(exception))) + "\"," +
-                        "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
-                        "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
-                        "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
-                        "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
-                        "}",
-                uncompressedString);
+        String expected = "{" +
+                "\"version\": \"1.1\"," +
+                "\"host\": \"" + HOSTNAME + "\"," +
+                "\"timestamp\": " + GelfLayout.formatTimestamp(events.get(2).getTimeMillis()) + "," +
+                "\"level\": 3," +
+                "\"_thread\": \"" + threadName + "\"," +
+                "\"_logger\": \"\"," +
+                "\"short_message\": \"" + LINE3 + "\"," +
+                "\"full_message\": \"" + String.valueOf(JsonStringEncoder.getInstance().quoteAsString(
+                GelfLayout.formatThrowable(exception))) + "\"," +
+                "\"_" + KEY1 + "\": \"" + VALUE1 + "\"," +
+                "\"_" + KEY2 + "\": \"" + VALUE2 + "\"," +
+                "\"_" + MDCKEY1 + "\": \"" + MDCVALUE1 + "\"," +
+                "\"_" + MDCKEY2 + "\": \"" + MDCVALUE2 + "\"" +
+                "}";
         //@formatter:on
+        assertJsonEquals(expected, uncompressedString);
+        assertJsonEquals(expected, uncompressedString2);
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
new file mode 100644
index 0000000..810e18f
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/EncodingListAppender.java
@@ -0,0 +1,64 @@
+package org.apache.logging.log4j.test.appender;
+
+import org.apache.logging.log4j.core.Filter;
+import org.apache.logging.log4j.core.Layout;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.layout.ByteBufferDestination;
+import org.apache.logging.log4j.core.layout.SerializedLayout;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+/**
+ * This appender is primarily used for testing. Use in a real environment is discouraged as the
+ * List could eventually grow to cause an OutOfMemoryError.
+ *
+ * This appender will use {@link Layout#encode(Object, ByteBufferDestination)} (and not {@link Layout#toByteArray(LogEvent)}).
+ */
+public class EncodingListAppender extends ListAppender {
+
+    public EncodingListAppender(String name) {
+        super(name);
+    }
+
+    public EncodingListAppender(String name, Filter filter, Layout<? extends Serializable> layout, boolean newline, boolean raw) {
+        super(name, filter, layout, newline, raw);
+    }
+
+    private class Destination implements ByteBufferDestination {
+        ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4096]);
+        @Override
+        public ByteBuffer getByteBuffer() {
+            return byteBuffer;
+        }
+
+        @Override
+        public ByteBuffer drain(final ByteBuffer buf) {
+            throw new IllegalStateException("Unexpected message larger than 4096 bytes");
+        }
+    }
+
+    @Override
+    public synchronized void append(final LogEvent event) {
+        final Layout<? extends Serializable> layout = getLayout();
+        if (layout == null) {
+            events.add(event);
+        } else if (layout instanceof SerializedLayout) {
+            Destination content = new Destination();
+            content.byteBuffer.put(layout.getHeader());
+            layout.encode(event, content);
+            content.getByteBuffer().rewind();
+            byte[] record = new byte[content.getByteBuffer().remaining()];
+            content.getByteBuffer().get(record);
+            data.add(record);
+        } else {
+            Destination content = new Destination();
+            layout.encode(event, content);
+            content.getByteBuffer().rewind();
+            byte[] record = new byte[content.getByteBuffer().remaining()];
+            content.getByteBuffer().get(record);
+            write(record);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/58152b79/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
index 05fa157..cd9ec82 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/test/appender/ListAppender.java
@@ -36,6 +36,9 @@ import org.apache.logging.log4j.core.layout.SerializedLayout;
 /**
  * This appender is primarily used for testing. Use in a real environment is discouraged as the
  * List could eventually grow to cause an OutOfMemoryError.
+ *
+ * This appender will use {@link Layout#toByteArray(LogEvent)}.
+ *
  * @see org.apache.logging.log4j.junit.LoggerContextRule#getListAppender(String) ILC.getListAppender
  */
 @Plugin(name = "List", category = "Core", elementType = "appender", printObject = true)
@@ -45,11 +48,11 @@ public class ListAppender extends AbstractAppender {
 
     // Use CopyOnWriteArrayList?
 
-    private final List<LogEvent> events = new ArrayList<>();
+    final List<LogEvent> events = new ArrayList<>();
 
     private final List<String> messages = new ArrayList<>();
 
-    private final List<byte[]> data = new ArrayList<>();
+    final List<byte[]> data = new ArrayList<>();
 
     private final boolean newLine;
 
@@ -93,7 +96,7 @@ public class ListAppender extends AbstractAppender {
         }
     }
 
-    private void write(final byte[] bytes) {
+    void write(final byte[] bytes) {
         if (raw) {
             data.add(bytes);
             return;


[09/10] logging-log4j2 git commit: Merge branch 'master' into gelf-layout-gc-free

Posted by mi...@apache.org.
Merge branch 'master' into gelf-layout-gc-free


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

Branch: refs/heads/gelf-layout-gc-free
Commit: 7467e5dc2066b1ab553c3744b389b09b0bc28516
Parents: 920cddd f1e5063
Author: Mikael Ståldal <mi...@magine.com>
Authored: Tue Mar 8 16:15:53 2016 +0100
Committer: Mikael Ståldal <mi...@magine.com>
Committed: Tue Mar 8 16:15:53 2016 +0100

----------------------------------------------------------------------
 .../message/ReusableParameterizedMessage.java   |  23 ++-
 .../log4j/message/ParameterFormatterTest.java   | 193 +++++++++++++++++++
 .../ReusableParameterizedMessageTest.java       |  59 ++++++
 .../core/async/AsyncLoggerConfigDisruptor.java  |   6 +-
 .../log4j/core/async/RingBufferLogEvent.java    |   6 +-
 .../logging/log4j/core/impl/Log4jLogEvent.java  |  16 +-
 .../logging/log4j/core/net/SmtpManager.java     |   7 +-
 .../log4j/core/layout/PatternLayoutTest.java    |  67 +++++--
 8 files changed, 347 insertions(+), 30 deletions(-)
----------------------------------------------------------------------



[03/10] logging-log4j2 git commit: LOG4J2-1296 bugfix in ReusableParameterizedMessage: calling getFormattedMessage() multiple times should return correct results

Posted by mi...@apache.org.
LOG4J2-1296 bugfix in ReusableParameterizedMessage: calling getFormattedMessage() multiple times should return correct results


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

Branch: refs/heads/gelf-layout-gc-free
Commit: 98ded70186d34bfc664094d5d120b63895ba9668
Parents: f157cc2
Author: rpopma <rp...@apache.org>
Authored: Wed Mar 9 00:58:31 2016 +1100
Committer: rpopma <rp...@apache.org>
Committed: Wed Mar 9 00:58:31 2016 +1100

----------------------------------------------------------------------
 .../message/ReusableParameterizedMessage.java   | 23 ++++++++++++--------
 1 file changed, 14 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/98ded701/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index 7d2b1d5..bd6205f 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -31,8 +31,8 @@ import org.apache.logging.log4j.util.PerformanceSensitive;
 public class ReusableParameterizedMessage implements ReusableMessage {
 
     private static final long serialVersionUID = 7800075879295123856L;
+    private static ThreadLocal<StringBuilder> buffer = new ThreadLocal<>();
 
-    private final StringBuilder buffer = new StringBuilder(2048);
     private String messagePattern;
     private int argCount;
     private transient Object[] varargs;
@@ -55,8 +55,6 @@ public class ReusableParameterizedMessage implements ReusableMessage {
 
     private void init(String messagePattern, int argCount, Object[] paramArray) {
         this.varargs = null;
-        this.buffer.setLength(0);
-
         this.messagePattern = messagePattern;
         this.argCount= argCount;
         int usedCount = ParameterFormatter.countArgumentPlaceholders(messagePattern);
@@ -70,10 +68,6 @@ public class ReusableParameterizedMessage implements ReusableMessage {
         }
     }
 
-    public StringBuilder get() {
-        return buffer;
-    }
-
     ReusableParameterizedMessage set(String messagePattern, Object... arguments) {
         init(messagePattern, arguments == null ? 0 : arguments.length, arguments);
         varargs = arguments;
@@ -227,8 +221,19 @@ public class ReusableParameterizedMessage implements ReusableMessage {
      */
     @Override
     public String getFormattedMessage() {
-        formatTo(buffer);
-        return buffer.toString();
+        final StringBuilder sb = getBuffer();
+        formatTo(sb);
+        return sb.toString();
+    }
+
+    private StringBuilder getBuffer() {
+        StringBuilder result = buffer.get();
+        if (result == null) {
+            result = new StringBuilder(Math.min(512, messagePattern.length() * 2));
+            buffer.set(result);
+        }
+        result.setLength(0);
+        return result;
     }
 
     @Override