From ddd7569bc8027b1221f1f38c116bc0fa80152660 Mon Sep 17 00:00:00 2001 From: wardseptember Date: Tue, 30 Dec 2025 15:42:27 +0800 Subject: [PATCH 1/2] fix: compatible with slf4j 2.x version --- .../main/java/org/slf4j/TrpcMDCAdapter.java | 100 ++++++------------ 1 file changed, 35 insertions(+), 65 deletions(-) diff --git a/trpc-core/src/main/java/org/slf4j/TrpcMDCAdapter.java b/trpc-core/src/main/java/org/slf4j/TrpcMDCAdapter.java index 8b76ddccc..7d8baa238 100644 --- a/trpc-core/src/main/java/org/slf4j/TrpcMDCAdapter.java +++ b/trpc-core/src/main/java/org/slf4j/TrpcMDCAdapter.java @@ -13,14 +13,17 @@ import com.alibaba.ttl.TransmittableThreadLocal; import com.tencent.trpc.core.utils.StringUtils; +import org.slf4j.spi.MDCAdapter; + import java.util.Deque; -import java.lang.reflect.Field; +import java.util.ArrayDeque; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import org.slf4j.spi.MDCAdapter; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ConcurrentMap; /** * TrpcMDCAdapter @@ -42,6 +45,9 @@ public class TrpcMDCAdapter implements MDCAdapter { private final ThreadLocal> copyOnInheritThreadLocal = new TransmittableThreadLocal<>(); + private final ThreadLocal>> threadLocalDequeMap = + ThreadLocal.withInitial(ConcurrentHashMap::new); + /** * Keeps track of the last operation performed */ @@ -49,15 +55,7 @@ public class TrpcMDCAdapter implements MDCAdapter { static { mtcMDCAdapter = new TrpcMDCAdapter(); - try { - // In SLF4J 2.0, MDC.mdcAdapter is no longer directly accessible - // We need to use reflection to set it - Field field = MDC.class.getDeclaredField("mdcAdapter"); - field.setAccessible(true); - field.set(null, mtcMDCAdapter); - } catch (Exception e) { - throw new RuntimeException("Failed to initialize TrpcMDCAdapter", e); - } + MDC.setMDCAdapter(mtcMDCAdapter); } public static MDCAdapter init() { @@ -188,77 +186,49 @@ private Map duplicateAndInsertNewMap(Map oldMap) return newMap; } - /** - * Push a context value as identified with the key parameter into the current thread's context map. - * This is a SLF4J 2.0 new method for supporting MDC stack operations. - * - * @param key the key - * @param value the value to push - * @throws NullPointerException in case the "key" parameter is null - */ @Override public void pushByKey(String key, String value) { Objects.requireNonNull(key, "key cannot be null"); - Map oldMap = copyOnInheritThreadLocal.get(); - Integer lastOp = getAndSetLastOperation(); - if (wasLastOpReadOrNull(lastOp) || oldMap == null) { - Map newMap = duplicateAndInsertNewMap(oldMap); - newMap.put(key, value); - } else { - oldMap.put(key, value); - } + ConcurrentMap> dequeMap = threadLocalDequeMap.get(); + ConcurrentLinkedDeque deque = dequeMap.computeIfAbsent(key, k -> new ConcurrentLinkedDeque<>()); + deque.push(value); } - /** - * Pop the context identified by key parameter from the current thread's context map. - * This is a SLF4J 2.0 new method for supporting MDC stack operations. - * - * @param key the key - * @return the value removed, or null if there was no value for the key - * @throws NullPointerException in case the "key" parameter is null - */ @Override public String popByKey(String key) { Objects.requireNonNull(key, "key cannot be null"); - Map oldMap = copyOnInheritThreadLocal.get(); - if (oldMap == null) { + ConcurrentMap> dequeMap = threadLocalDequeMap.get(); + ConcurrentLinkedDeque deque = dequeMap.get(key); + if (deque == null || deque.isEmpty()) { return null; } - Integer lastOp = getAndSetLastOperation(); - if (wasLastOpReadOrNull(lastOp)) { - Map newMap = duplicateAndInsertNewMap(oldMap); - return newMap.remove(key); - } else { - return oldMap.remove(key); + String value = deque.pollFirst(); + if (deque.isEmpty()) { + dequeMap.remove(key); } + return value; } - /** - * Clear all the entries in the deque identified by the key parameter. - * This is a SLF4J 2.0.7+ new method for clearing MDC stacks. - * - * @param key the key - * @throws NullPointerException in case the "key" parameter is null - */ @Override - public void clearDequeByKey(String key) { - Objects.requireNonNull(key, "key cannot be null"); - remove(key); + public Deque getCopyOfDequeByKey(String key) { + if (key == null) { + return null; + } + ConcurrentMap> dequeMap = threadLocalDequeMap.get(); + ConcurrentLinkedDeque deque = dequeMap.get(key); + if (deque == null) { + return null; + } + return new ArrayDeque<>(deque); } - /** - * Get a copy of the deque identified by the key parameter. - * This is a SLF4J 2.0 new method for supporting MDC stack operations. - * Since our implementation uses a simple Map, we return null to indicate no deque. - * - * @param key the key - * @return null (this implementation does not support deques) - */ @Override - public Deque getCopyOfDequeByKey(String key) { - // This implementation uses a simple Map structure, not Deque - // Return null to indicate no deque exists for the key - return null; + public void clearDequeByKey(String key) { + if (key == null) { + return; + } + ConcurrentMap> dequeMap = threadLocalDequeMap.get(); + dequeMap.remove(key); } } \ No newline at end of file From 8ffd1b81531d3cc815012a33e5dfcf05126b643b Mon Sep 17 00:00:00 2001 From: wardseptember Date: Tue, 30 Dec 2025 19:54:21 +0800 Subject: [PATCH 2/2] fix: compatible with slf4j 2.x version --- CHANGELOG.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dedc8ec5..798713d21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,25 +1,5 @@ # Change Log -## v2.0.1-SNAPSHOT (Unreleased) - -### Breaking Changes - -- **deps**: Upgrade slf4j-api from 1.7.36 to 2.0.17 for Spring Boot 3.5.0 compatibility -- **deps**: Upgrade logback from 1.2.13 to 1.4.14 for SLF4J 2.0 support -- **deps**: Replace log4j-slf4j-impl with log4j-slf4j2-impl (2.24.3) for SLF4J 2.0 bridge - -### Enhancements - -- **core**: Implement SLF4J 2.0 new MDCAdapter interface methods (pushByKey, popByKey, clearDequeByKey, getCopyOfDequeByKey) in TrpcMDCAdapter -- **core**: Use reflection to initialize MDC adapter in SLF4J 2.0 compatible way -- **deps**: Ensure all slf4j dependencies are upgraded to 2.0.17 across all modules - -### Compatibility - -- **java**: Fully compatible with JDK 17 -- **spring**: Fully compatible with Spring Boot 3.5.0 -- **jakarta**: Aligned with Jakarta EE 10 - ## v1.1.0 (2023-12-20) ### Features