java.lang.Object
stincmale.server.util.logging.TransferableMdc
- All Implemented Interfaces:
Closeable
,AutoCloseable
,MDCAdapter
@NotThreadSafe public final class TransferableMdc extends Object implements MDCAdapter, Closeable
A read-only
MDCAdapter
which allows to copy the state of MDC
between threads.
This class is not thread-safe but correctly transfers MDC
if used according to the provided idiom.
Usage examples.
Correct:
TransferableMdc outerMdc = TransferableMdc.current();
executor.submit(() -> {
try (var transferredMdc = outerMdc.transfer()) {
logger.info("This call can access contents of outerMdc via org.slf4j.MDC");
}
logger.info("This call cannot access contents of outerMdc via org.slf4j.MDC");
});
Incorrect 1:
executor.submit(() -> {
try (var transferredMdc = TransferableMdc.current().transfer()) {
//...
}
});
This is incorrect because we do not have access to the context data of the "outer" thread.
Incorrect 2:
TransferableMdc outerMdc = TransferableMdc.current();
executor.submit(() -> {//task1
try (var transferredMdc = outerMdc.transfer()) {
//...
}
});
executor.submit(() -> {//task2
try (var transferredMdc = outerMdc.transfer()) {
//...
}
});
This is incorrect because task1
and task2
may be executed concurrently and hence
methods transfer()
and close()
may be executed concurrently, and these methods are not thread-safe.
In order to prevent such incorrect usages, close()
throws IllegalStateException
if detects that the method is called more than once.
The correct usage idiom:
TransferableMdc outerMdc1 = TransferableMdc.current();
executor.submit(() -> {//task1
try (var transferredMdc = outerMdc1.transfer()) {
//...
}
});
TransferableMdc outerMdc2 = TransferableMdc.current();
executor.submit(() -> {//task2
try (var transferredMdc = outerMdc2.transfer()) {
//...
}
});
-
Method Summary
Modifier and Type Method Description void
clear()
void
close()
static TransferableMdc
current()
String
get(String key)
Map<String,String>
getCopyOfContextMap()
void
put(String key, String val)
void
remove(String key)
void
setContextMap(Map<String,String> contextMap)
String
toString()
TransferableMdc
transfer()
Overrides the current thread'sMDC
with the state ofTransferableMdc
and retains the original state of the currentMDC
.
-
Method Details
-
current
- Returns:
- New
TransferableMdc
which state is identical to the current thread's state ofMDC
.
-
transfer
Overrides the current thread'sMDC
with the state ofTransferableMdc
and retains the original state of the currentMDC
.- Returns:
this
.- See Also:
close()
-
close
- Specified by:
close
in interfaceAutoCloseable
- Specified by:
close
in interfaceCloseable
- Throws:
IllegalStateException
- if detects that the method is called more than once. Such detection is not guaranteed and is provided on the best effort basis.
-
put
- Specified by:
put
in interfaceMDCAdapter
- Throws:
UnsupportedOperationException
- Always.
-
get
- Specified by:
get
in interfaceMDCAdapter
-
remove
- Specified by:
remove
in interfaceMDCAdapter
- Throws:
UnsupportedOperationException
- Always.
-
clear
- Specified by:
clear
in interfaceMDCAdapter
- Throws:
UnsupportedOperationException
- Always.
-
getCopyOfContextMap
- Specified by:
getCopyOfContextMap
in interfaceMDCAdapter
-
setContextMap
public final void setContextMap(@Nullable Map<String,String> contextMap) throws UnsupportedOperationException- Specified by:
setContextMap
in interfaceMDCAdapter
- Throws:
UnsupportedOperationException
- Always.
-
toString
-