Skip to content

Commit 5acabb5

Browse files
fix: compatible with slf4j 2.x version (#114)
* fix: compatible with slf4j 2.x version * fix: compatible with slf4j 2.x version
1 parent c18183c commit 5acabb5

File tree

2 files changed

+35
-85
lines changed

2 files changed

+35
-85
lines changed

CHANGELOG.md

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
11
# Change Log
22

3-
## v2.0.1-SNAPSHOT (Unreleased)
4-
5-
### Breaking Changes
6-
7-
- **deps**: Upgrade slf4j-api from 1.7.36 to 2.0.17 for Spring Boot 3.5.0 compatibility
8-
- **deps**: Upgrade logback from 1.2.13 to 1.4.14 for SLF4J 2.0 support
9-
- **deps**: Replace log4j-slf4j-impl with log4j-slf4j2-impl (2.24.3) for SLF4J 2.0 bridge
10-
11-
### Enhancements
12-
13-
- **core**: Implement SLF4J 2.0 new MDCAdapter interface methods (pushByKey, popByKey, clearDequeByKey, getCopyOfDequeByKey) in TrpcMDCAdapter
14-
- **core**: Use reflection to initialize MDC adapter in SLF4J 2.0 compatible way
15-
- **deps**: Ensure all slf4j dependencies are upgraded to 2.0.17 across all modules
16-
17-
### Compatibility
18-
19-
- **java**: Fully compatible with JDK 17
20-
- **spring**: Fully compatible with Spring Boot 3.5.0
21-
- **jakarta**: Aligned with Jakarta EE 10
22-
233
## v1.1.0 (2023-12-20)
244

255
### Features

trpc-core/src/main/java/org/slf4j/TrpcMDCAdapter.java

Lines changed: 35 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,17 @@
1313

1414
import com.alibaba.ttl.TransmittableThreadLocal;
1515
import com.tencent.trpc.core.utils.StringUtils;
16+
import org.slf4j.spi.MDCAdapter;
17+
1618
import java.util.Deque;
17-
import java.lang.reflect.Field;
19+
import java.util.ArrayDeque;
1820
import java.util.HashMap;
1921
import java.util.Map;
2022
import java.util.Objects;
2123
import java.util.Optional;
2224
import java.util.concurrent.ConcurrentHashMap;
23-
import org.slf4j.spi.MDCAdapter;
25+
import java.util.concurrent.ConcurrentLinkedDeque;
26+
import java.util.concurrent.ConcurrentMap;
2427

2528
/**
2629
* TrpcMDCAdapter
@@ -42,22 +45,17 @@ public class TrpcMDCAdapter implements MDCAdapter {
4245

4346
private final ThreadLocal<Map<String, String>> copyOnInheritThreadLocal = new TransmittableThreadLocal<>();
4447

48+
private final ThreadLocal<ConcurrentMap<String, ConcurrentLinkedDeque<String>>> threadLocalDequeMap =
49+
ThreadLocal.withInitial(ConcurrentHashMap::new);
50+
4551
/**
4652
* Keeps track of the last operation performed
4753
*/
4854
private final ThreadLocal<Integer> lastOperation = new ThreadLocal<>();
4955

5056
static {
5157
mtcMDCAdapter = new TrpcMDCAdapter();
52-
try {
53-
// In SLF4J 2.0, MDC.mdcAdapter is no longer directly accessible
54-
// We need to use reflection to set it
55-
Field field = MDC.class.getDeclaredField("mdcAdapter");
56-
field.setAccessible(true);
57-
field.set(null, mtcMDCAdapter);
58-
} catch (Exception e) {
59-
throw new RuntimeException("Failed to initialize TrpcMDCAdapter", e);
60-
}
58+
MDC.setMDCAdapter(mtcMDCAdapter);
6159
}
6260

6361
public static MDCAdapter init() {
@@ -188,77 +186,49 @@ private Map<String, String> duplicateAndInsertNewMap(Map<String, String> oldMap)
188186
return newMap;
189187
}
190188

191-
/**
192-
* Push a context value as identified with the key parameter into the current thread's context map.
193-
* This is a SLF4J 2.0 new method for supporting MDC stack operations.
194-
*
195-
* @param key the key
196-
* @param value the value to push
197-
* @throws NullPointerException in case the "key" parameter is null
198-
*/
199189
@Override
200190
public void pushByKey(String key, String value) {
201191
Objects.requireNonNull(key, "key cannot be null");
202-
Map<String, String> oldMap = copyOnInheritThreadLocal.get();
203-
Integer lastOp = getAndSetLastOperation();
204-
if (wasLastOpReadOrNull(lastOp) || oldMap == null) {
205-
Map<String, String> newMap = duplicateAndInsertNewMap(oldMap);
206-
newMap.put(key, value);
207-
} else {
208-
oldMap.put(key, value);
209-
}
192+
ConcurrentMap<String, ConcurrentLinkedDeque<String>> dequeMap = threadLocalDequeMap.get();
193+
ConcurrentLinkedDeque<String> deque = dequeMap.computeIfAbsent(key, k -> new ConcurrentLinkedDeque<>());
194+
deque.push(value);
210195
}
211196

212-
/**
213-
* Pop the context identified by key parameter from the current thread's context map.
214-
* This is a SLF4J 2.0 new method for supporting MDC stack operations.
215-
*
216-
* @param key the key
217-
* @return the value removed, or null if there was no value for the key
218-
* @throws NullPointerException in case the "key" parameter is null
219-
*/
220197
@Override
221198
public String popByKey(String key) {
222199
Objects.requireNonNull(key, "key cannot be null");
223-
Map<String, String> oldMap = copyOnInheritThreadLocal.get();
224-
if (oldMap == null) {
200+
ConcurrentMap<String, ConcurrentLinkedDeque<String>> dequeMap = threadLocalDequeMap.get();
201+
ConcurrentLinkedDeque<String> deque = dequeMap.get(key);
202+
if (deque == null || deque.isEmpty()) {
225203
return null;
226204
}
227-
Integer lastOp = getAndSetLastOperation();
228-
if (wasLastOpReadOrNull(lastOp)) {
229-
Map<String, String> newMap = duplicateAndInsertNewMap(oldMap);
230-
return newMap.remove(key);
231-
} else {
232-
return oldMap.remove(key);
205+
String value = deque.pollFirst();
206+
if (deque.isEmpty()) {
207+
dequeMap.remove(key);
233208
}
209+
return value;
234210
}
235211

236-
/**
237-
* Clear all the entries in the deque identified by the key parameter.
238-
* This is a SLF4J 2.0.7+ new method for clearing MDC stacks.
239-
*
240-
* @param key the key
241-
* @throws NullPointerException in case the "key" parameter is null
242-
*/
243212
@Override
244-
public void clearDequeByKey(String key) {
245-
Objects.requireNonNull(key, "key cannot be null");
246-
remove(key);
213+
public Deque<String> getCopyOfDequeByKey(String key) {
214+
if (key == null) {
215+
return null;
216+
}
217+
ConcurrentMap<String, ConcurrentLinkedDeque<String>> dequeMap = threadLocalDequeMap.get();
218+
ConcurrentLinkedDeque<String> deque = dequeMap.get(key);
219+
if (deque == null) {
220+
return null;
221+
}
222+
return new ArrayDeque<>(deque);
247223
}
248224

249-
/**
250-
* Get a copy of the deque identified by the key parameter.
251-
* This is a SLF4J 2.0 new method for supporting MDC stack operations.
252-
* Since our implementation uses a simple Map, we return null to indicate no deque.
253-
*
254-
* @param key the key
255-
* @return null (this implementation does not support deques)
256-
*/
257225
@Override
258-
public Deque<String> getCopyOfDequeByKey(String key) {
259-
// This implementation uses a simple Map structure, not Deque
260-
// Return null to indicate no deque exists for the key
261-
return null;
226+
public void clearDequeByKey(String key) {
227+
if (key == null) {
228+
return;
229+
}
230+
ConcurrentMap<String, ConcurrentLinkedDeque<String>> dequeMap = threadLocalDequeMap.get();
231+
dequeMap.remove(key);
262232
}
263233

264234
}

0 commit comments

Comments
 (0)