You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rp...@apache.org on 2018/01/07 11:12:40 UTC

[1/2] logging-log4j2 git commit: LOG4J2-2158 make inherited log event context data immutable when using CopyOnWriteThreadContextMap

Repository: logging-log4j2
Updated Branches:
  refs/heads/master e064ac404 -> 2352052d0


LOG4J2-2158 make inherited log event context data immutable when using CopyOnWriteThreadContextMap


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

Branch: refs/heads/master
Commit: f1f3945b707d8a590d2fb60624673484771b7d31
Parents: e064ac4
Author: Björn Kautler <Bj...@Kautler.net>
Authored: Fri Dec 22 15:41:45 2017 +0100
Committer: Björn Kautler <Bj...@Kautler.net>
Committed: Sun Jan 7 01:44:10 2018 +0100

----------------------------------------------------------------------
 .../org/apache/logging/log4j/ThreadContext.java |   2 +
 .../CopyOnWriteSortedArrayThreadContextMap.java |   7 +-
 .../apache/logging/log4j/ThreadContextTest.java |   3 +
 .../impl/ThreadContextDataInjectorTest.java     | 121 +++++++++++++++++++
 4 files changed, 132 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f1f3945b/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java b/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
index b37b0f9..fc018b9 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
@@ -225,6 +225,8 @@ public final class ThreadContext {
         }
         if (contextMap instanceof ReadOnlyThreadContextMap) {
             readOnlyContextMap = (ReadOnlyThreadContextMap) contextMap;
+        } else {
+            readOnlyContextMap = null;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f1f3945b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
index 05b783c..024edc6 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
@@ -72,7 +72,12 @@ class CopyOnWriteSortedArrayThreadContextMap implements ReadOnlyThreadContextMap
             return new InheritableThreadLocal<StringMap>() {
                 @Override
                 protected StringMap childValue(final StringMap parentValue) {
-                    return parentValue != null ? createStringMap(parentValue) : null;
+                    if (parentValue == null) {
+                        return null;
+                    }
+                    StringMap stringMap = createStringMap(parentValue);
+                    stringMap.freeze();
+                    return stringMap;
                 }
             };
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f1f3945b/log4j-api/src/test/java/org/apache/logging/log4j/ThreadContextTest.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/test/java/org/apache/logging/log4j/ThreadContextTest.java b/log4j-api/src/test/java/org/apache/logging/log4j/ThreadContextTest.java
index ea98b36..a1d1101 100644
--- a/log4j-api/src/test/java/org/apache/logging/log4j/ThreadContextTest.java
+++ b/log4j-api/src/test/java/org/apache/logging/log4j/ThreadContextTest.java
@@ -28,6 +28,9 @@ import static org.junit.Assert.*;
  *
  */
 public class ThreadContextTest {
+    public static void reinitThreadContext() {
+        ThreadContext.init();
+    }
 
     @Test
     public void testPush() {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/f1f3945b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java
new file mode 100644
index 0000000..2742da1
--- /dev/null
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjectorTest.java
@@ -0,0 +1,121 @@
+package org.apache.logging.log4j.core.impl;
+
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.ThreadContextTest;
+import org.apache.logging.log4j.core.ContextDataInjector;
+import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap;
+import org.apache.logging.log4j.util.PropertiesUtil;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+import org.apache.logging.log4j.util.StringMap;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import static java.util.Arrays.asList;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.apache.logging.log4j.ThreadContext.getThreadContextMap;
+import static org.apache.logging.log4j.core.impl.ContextDataInjectorFactory.createInjector;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+@RunWith(Parameterized.class)
+public class ThreadContextDataInjectorTest {
+    @Parameters(name = "{0}")
+    public static Collection<String[]> threadContextMapClassNames() {
+        return asList(new String[][] {
+                { "org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap", "org.apache.logging.log4j.spi.CopyOnWriteSortedArrayThreadContextMap" },
+                { "org.apache.logging.log4j.spi.GarbageFreeSortedArrayThreadContextMap", "org.apache.logging.log4j.spi.GarbageFreeSortedArrayThreadContextMap" },
+                { "org.apache.logging.log4j.spi.DefaultThreadContextMap", null }
+        });
+    }
+
+    @Parameter
+    public String threadContextMapClassName;
+
+    @Parameter(value = 1)
+    public String readOnlythreadContextMapClassName;
+
+    @Before
+    public void before() {
+        System.setProperty("log4j2.threadContextMap", threadContextMapClassName);
+    }
+
+    @After
+    public void after() {
+        ThreadContext.remove("foo");
+        ThreadContext.remove("baz");
+        System.clearProperty("log4j2.threadContextMap");
+        System.clearProperty("log4j2.isThreadContextMapInheritable");
+    }
+
+    private void testContextDataInjector() {
+        ReadOnlyThreadContextMap readOnlythreadContextMap = getThreadContextMap();
+        assertThat("thread context map class name",
+                   (readOnlythreadContextMap == null) ? null : readOnlythreadContextMap.getClass().getName(),
+                   is(equalTo(readOnlythreadContextMapClassName)));
+
+        ContextDataInjector contextDataInjector = createInjector();
+        StringMap stringMap = contextDataInjector.injectContextData(null, new SortedArrayStringMap());
+
+        assertThat("thread context map", ThreadContext.getContext(), allOf(hasEntry("foo", "bar"), not(hasKey("baz"))));
+        assertThat("context map", stringMap.toMap(), allOf(hasEntry("foo", "bar"), not(hasKey("baz"))));
+
+        if (!stringMap.isFrozen()) {
+            stringMap.clear();
+            assertThat("thread context map", ThreadContext.getContext(), allOf(hasEntry("foo", "bar"), not(hasKey("baz"))));
+            assertThat("context map", stringMap.toMap().entrySet(), is(empty()));
+        }
+
+        ThreadContext.put("foo", "bum");
+        ThreadContext.put("baz", "bam");
+
+        assertThat("thread context map", ThreadContext.getContext(), allOf(hasEntry("foo", "bum"), hasEntry("baz", "bam")));
+        if (stringMap.isFrozen()) {
+            assertThat("context map", stringMap.toMap(), allOf(hasEntry("foo", "bar"), not(hasKey("baz"))));
+        } else {
+            assertThat("context map", stringMap.toMap().entrySet(), is(empty()));
+        }
+    }
+
+    private void prepareThreadContext(boolean isThreadContextMapInheritable) {
+        System.setProperty("log4j2.isThreadContextMapInheritable", Boolean.toString(isThreadContextMapInheritable));
+        PropertiesUtil.getProperties().reload();
+        ThreadContextTest.reinitThreadContext();
+        ThreadContext.remove("baz");
+        ThreadContext.put("foo", "bar");
+    }
+
+    @Test
+    public void testThreadContextImmutability() {
+        prepareThreadContext(false);
+        testContextDataInjector();
+    }
+
+    @Test
+    public void testInheritableThreadContextImmutability() throws Throwable {
+        prepareThreadContext(true);
+        try {
+            newSingleThreadExecutor().submit(new Runnable() {
+                @Override
+                public void run() {
+                    testContextDataInjector();
+                }
+            }).get();
+        } catch (ExecutionException ee) {
+            throw ee.getCause();
+        }
+    }
+}


[2/2] logging-log4j2 git commit: LOG4J2-2158 (update change log) Fixed bug where ThreadContext map was cleared, resulting in entries being only available for one log event.

Posted by rp...@apache.org.
LOG4J2-2158 (update change log) Fixed bug where ThreadContext map was cleared, resulting in entries being only available for one log event.


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

Branch: refs/heads/master
Commit: 2352052d0bc797ede29a5b4a8897200aa49a8c43
Parents: f1f3945
Author: rpopma <rp...@apache.org>
Authored: Sun Jan 7 20:06:38 2018 +0900
Committer: rpopma <rp...@apache.org>
Committed: Sun Jan 7 20:06:38 2018 +0900

----------------------------------------------------------------------
 src/changes/changes.xml | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/2352052d/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 0f48c06..a53c85f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
          - "remove" - Removed
     -->
     <release version="2.10.1" date="2017-xx-xx" description="GA Release 2.10.1">
+      <action issue="LOG4J2-2158" dev="rpopma" type="fix" due-to="Björn Kautler">
+        Fixed bug where ThreadContext map was cleared, resulting in entries being only available for one log event.
+      </action>
       <action issue="LOG4J2-2002" dev="mikes" type="fix" due-to="Paul Burrowes">
         Avoid null attribute values in DefaultConfigurationBuilder.
       </action>