You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ra...@apache.org on 2026/10/01 17:51:02 UTC
(logging-log4j2) 33/33: Restore UNCACHED thread name updates in AsyncLogger (#4280)
This is an automated email from the ASF dual-hosted git repository.
ramanathan1504 pushed a commit to branch port/2.27.0-fixes-to-2.26.x
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit 27c3cac85d5c1321ddfa091ffdd6eab39e7fab8b
Author: Andrew <an...@gmail.com>
AuthorDate: Thu Oct 1 18:21:47 2026 +0300
Restore UNCACHED thread name updates in AsyncLogger (#4280)
Fix stale thread names in fully asynchronous loggers using the `UNCACHED` strategy.
---------
Co-authored-by: Ramanathan <ra...@apache.org>
(cherry picked from commit e076aa5f230c77f0a873655c4308913dbdc35b28)
---
.../async/AsyncLoggerTestUncachedThreadName.java | 76 --------------
.../async/AsyncLoggerUncachedThreadNameTest.java | 113 +++++++++++++++++++++
.../logging/log4j/core/async/AsyncLogger.java | 8 ++
.../core/async/RingBufferLogEventTranslator.java | 5 +-
.../4275_fix_uncached_async_logger_thread_name.xml | 13 +++
5 files changed, 138 insertions(+), 77 deletions(-)
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTestUncachedThreadName.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTestUncachedThreadName.java
deleted file mode 100644
index 12fa5b07e3..0000000000
--- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerTestUncachedThreadName.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.core.async;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.core.config.ConfigurationFactory;
-import org.apache.logging.log4j.core.test.CoreLoggerContexts;
-import org.apache.logging.log4j.core.test.junit.Tags;
-import org.apache.logging.log4j.core.util.Constants;
-import org.apache.logging.log4j.util.Strings;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Tag;
-import org.junit.jupiter.api.Test;
-
-@Tag(Tags.ASYNC_LOGGERS)
-class AsyncLoggerTestUncachedThreadName {
-
- @BeforeAll
- static void beforeClass() {
- System.setProperty("AsyncLogger.ThreadNameStrategy", "UNCACHED");
- System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, AsyncLoggerContextSelector.class.getName());
- System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, "AsyncLoggerTest.xml");
- }
-
- @AfterAll
- static void afterClass() {
- System.setProperty(Constants.LOG4J_CONTEXT_SELECTOR, Strings.EMPTY);
- }
-
- @Test
- void testAsyncLogUsesCurrentThreadName() throws Exception {
- final File file = new File("target", "AsyncLoggerTest.log");
- // System.out.println(f.getAbsolutePath());
- file.delete();
- final Logger log = LogManager.getLogger("com.foo.Bar");
- final String msg = "Async logger msg";
- log.info(msg);
- Thread.currentThread().setName("MODIFIED-THREADNAME");
- log.info(msg);
- CoreLoggerContexts.stopLoggerContext(file); // stop async thread
-
- final BufferedReader reader = new BufferedReader(new FileReader(file));
- final String line1 = reader.readLine();
- final String line2 = reader.readLine();
- // System.out.println(line1);
- // System.out.println(line2);
- reader.close();
- file.delete();
- assertNotNull(line1, "line1");
- assertNotNull(line2, "line2");
- assertTrue(line1.endsWith(" INFO c.f.Bar [main] Async logger msg "), "line1");
- assertTrue(line2.endsWith(" INFO c.f.Bar [MODIFIED-THREADNAME] Async logger msg "), "line2");
- }
-}
diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerUncachedThreadNameTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerUncachedThreadNameTest.java
new file mode 100644
index 0000000000..25e3a26b51
--- /dev/null
+++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/async/AsyncLoggerUncachedThreadNameTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.core.async;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.test.CoreLoggerContexts;
+import org.apache.logging.log4j.core.test.junit.Tags;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+@Tag(Tags.ASYNC_LOGGERS)
+class AsyncLoggerUncachedThreadNameTest {
+
+ @BeforeAll
+ static void beforeClass() {
+ System.setProperty("log4j2.asyncLoggerThreadNameStrategy", "UNCACHED");
+ System.setProperty("log4j2.contextSelector", AsyncLoggerContextSelector.class.getName());
+ System.setProperty("log4j2.configurationFile", "AsyncLoggerTest.xml");
+ }
+
+ @AfterAll
+ static void afterClass() {
+ System.clearProperty("log4j2.asyncLoggerThreadNameStrategy");
+ System.clearProperty("log4j2.contextSelector");
+ System.clearProperty("log4j2.configurationFile");
+ }
+
+ @Test
+ void testAsyncLogUsesCurrentThreadName() throws Exception {
+ final File file = new File("target", "AsyncLoggerTest.log");
+ file.delete();
+ final Logger log = LogManager.getLogger("com.foo.Bar");
+
+ final String msg = "Async logger msg";
+ final AtomicReference<Thread> firstTaskThreadRef = new AtomicReference<>();
+ final AtomicReference<Thread> secondTaskThreadRef = new AtomicReference<>();
+ final ExecutorService executor = Executors.newSingleThreadExecutor();
+ try {
+ final Future<?> firstTask = executor.submit(() -> {
+ final Thread currentThread = Thread.currentThread();
+ final String originalThreadName = currentThread.getName();
+ final String expectedThreadName = "MODIFIED-THREADNAME-1";
+ firstTaskThreadRef.set(currentThread);
+ try {
+ currentThread.setName(expectedThreadName);
+ log.info(msg);
+ } finally {
+ currentThread.setName(originalThreadName);
+ }
+ return expectedThreadName;
+ });
+ final Future<?> secondTask = executor.submit(() -> {
+ final Thread currentThread = Thread.currentThread();
+ final String originalThreadName = currentThread.getName();
+ final String expectedThreadName = "MODIFIED-THREADNAME-2";
+ secondTaskThreadRef.set(currentThread);
+ try {
+ currentThread.setName(expectedThreadName);
+ log.info(msg);
+ } finally {
+ currentThread.setName(originalThreadName);
+ }
+ return expectedThreadName;
+ });
+ final String firstTaskThreadName = (String) firstTask.get();
+ final String secondTaskThreadName = (String) secondTask.get();
+ assertSame(firstTaskThreadRef.get(), secondTaskThreadRef.get(), "same async worker thread");
+ } finally {
+ executor.shutdown();
+ executor.awaitTermination(5, TimeUnit.SECONDS);
+ }
+
+ CoreLoggerContexts.stopLoggerContext(file);
+
+ try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+ final String line1 = reader.readLine();
+ final String line2 = reader.readLine();
+ assertNotNull(line1, "line1");
+ assertNotNull(line2, "line2");
+ assertTrue(line1.contains("MODIFIED-THREADNAME-1"), "line1");
+ assertTrue(line2.contains("MODIFIED-THREADNAME-2"), "line2");
+ }
+ }
+}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
index ff142abe8a..cbf6dca522 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
@@ -239,6 +239,7 @@ public class AsyncLogger extends Logger implements EventTranslatorVararg<RingBuf
final RingBufferLogEventTranslator translator = getCachedTranslator();
initTranslator(translator, fqcn, level, marker, message, thrown);
+ initTranslatorThreadValues(translator);
publish(translator);
}
@@ -266,6 +267,7 @@ public class AsyncLogger extends Logger implements EventTranslatorVararg<RingBuf
final RingBufferLogEventTranslator translator = getCachedTranslator();
initTranslator(translator, fqcn, location, level, marker, message, thrown);
+ initTranslatorThreadValues(translator);
publish(translator);
}
@@ -357,6 +359,12 @@ public class AsyncLogger extends Logger implements EventTranslatorVararg<RingBuf
);
}
+ private void initTranslatorThreadValues(final RingBufferLogEventTranslator translator) {
+ if (THREAD_NAME_CACHING_STRATEGY == ThreadNameCachingStrategy.UNCACHED) {
+ translator.updateThreadValues();
+ }
+ }
+
/**
* Returns the caller location if requested, {@code null} otherwise.
*
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
index f6fee9fcf5..db8567db43 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
@@ -130,8 +130,11 @@ public class RingBufferLogEventTranslator implements EventTranslator<RingBufferL
}
/**
+ * Updates the cached thread values from the current thread.
+ *
* @deprecated since 2.25.0. {@link RingBufferLogEventTranslator} instances should only be used on the thread that
- * created it.
+ * created them. This method is retained for internal use to refresh the thread name after
+ * {@link Thread#setName(String)}.
*/
@Deprecated
public void updateThreadValues() {
diff --git a/src/changelog/.2.x.x/4275_fix_uncached_async_logger_thread_name.xml b/src/changelog/.2.x.x/4275_fix_uncached_async_logger_thread_name.xml
new file mode 100644
index 0000000000..95b628ce51
--- /dev/null
+++ b/src/changelog/.2.x.x/4275_fix_uncached_async_logger_thread_name.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entry xmlns="https://logging.apache.org/xml/ns"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ https://logging.apache.org/xml/ns
+ https://logging.apache.org/xml/ns/log4j-changelog-0.xsd"
+ type="fixed">
+ <issue id="4275" link="https://github.com/apache/logging-log4j2/issues/4275"/>
+ <issue id="4280" link="https://github.com/apache/logging-log4j2/pull/4280"/>
+ <description format="asciidoc">
+ Fix stale thread names in fully asynchronous loggers using the `UNCACHED` strategy.
+ </description>
+</entry>