mirror of https://github.com/qos-ch/slf4j
add support for keyed deques in MDC
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
This commit is contained in:
parent
12b5a6b676
commit
f09e33dd15
|
|
@ -25,6 +25,7 @@
|
||||||
package org.slf4j;
|
package org.slf4j;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.slf4j.helpers.BasicMDCAdapter;
|
import org.slf4j.helpers.BasicMDCAdapter;
|
||||||
|
|
@ -64,6 +65,7 @@ import org.slf4j.spi.SLF4JServiceProvider;
|
||||||
public class MDC {
|
public class MDC {
|
||||||
|
|
||||||
static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA";
|
static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA";
|
||||||
|
private static final String MDC_APAPTER_CANNOT_BE_NULL_MESSAGE = "MDCAdapter cannot be null. See also " + NULL_MDCA_URL;
|
||||||
static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder";
|
static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder";
|
||||||
static MDCAdapter mdcAdapter;
|
static MDCAdapter mdcAdapter;
|
||||||
|
|
||||||
|
|
@ -116,7 +118,7 @@ public class MDC {
|
||||||
throw new IllegalArgumentException("key parameter cannot be null");
|
throw new IllegalArgumentException("key parameter cannot be null");
|
||||||
}
|
}
|
||||||
if (mdcAdapter == null) {
|
if (mdcAdapter == null) {
|
||||||
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
}
|
}
|
||||||
mdcAdapter.put(key, val);
|
mdcAdapter.put(key, val);
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +174,7 @@ public class MDC {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdcAdapter == null) {
|
if (mdcAdapter == null) {
|
||||||
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
}
|
}
|
||||||
return mdcAdapter.get(key);
|
return mdcAdapter.get(key);
|
||||||
}
|
}
|
||||||
|
|
@ -193,7 +195,7 @@ public class MDC {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mdcAdapter == null) {
|
if (mdcAdapter == null) {
|
||||||
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
}
|
}
|
||||||
mdcAdapter.remove(key);
|
mdcAdapter.remove(key);
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +205,7 @@ public class MDC {
|
||||||
*/
|
*/
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
if (mdcAdapter == null) {
|
if (mdcAdapter == null) {
|
||||||
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
}
|
}
|
||||||
mdcAdapter.clear();
|
mdcAdapter.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +219,7 @@ public class MDC {
|
||||||
*/
|
*/
|
||||||
public static Map<String, String> getCopyOfContextMap() {
|
public static Map<String, String> getCopyOfContextMap() {
|
||||||
if (mdcAdapter == null) {
|
if (mdcAdapter == null) {
|
||||||
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
}
|
}
|
||||||
return mdcAdapter.getCopyOfContextMap();
|
return mdcAdapter.getCopyOfContextMap();
|
||||||
}
|
}
|
||||||
|
|
@ -235,7 +237,7 @@ public class MDC {
|
||||||
*/
|
*/
|
||||||
public static void setContextMap(Map<String, String> contextMap) {
|
public static void setContextMap(Map<String, String> contextMap) {
|
||||||
if (mdcAdapter == null) {
|
if (mdcAdapter == null) {
|
||||||
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
}
|
}
|
||||||
mdcAdapter.setContextMap(contextMap);
|
mdcAdapter.setContextMap(contextMap);
|
||||||
}
|
}
|
||||||
|
|
@ -250,4 +252,48 @@ public class MDC {
|
||||||
return mdcAdapter;
|
return mdcAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a value into the deque(stack) referenced by 'key'.
|
||||||
|
*
|
||||||
|
* @param key identifies the appropriate stack
|
||||||
|
* @param value the value to push into the stack
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
static public void pushByKey(String key, String value) {
|
||||||
|
if (mdcAdapter == null) {
|
||||||
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
|
}
|
||||||
|
mdcAdapter.pushByKey(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop the stack referenced by 'key' and return the value possibly null.
|
||||||
|
*
|
||||||
|
* @param key identifies the deque(stack)
|
||||||
|
* @return the value just popped. May be null/
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
static public String popByKey(String key) {
|
||||||
|
if (mdcAdapter == null) {
|
||||||
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
|
}
|
||||||
|
return mdcAdapter.popByKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of the deque(stack) referenced by 'key'. May be null.
|
||||||
|
*
|
||||||
|
* @param key identifies the stack
|
||||||
|
* @return copy of stack referenced by 'key'. May be null.
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public Deque<String> getCopyOfDequeByKey(String key) {
|
||||||
|
if (mdcAdapter == null) {
|
||||||
|
throw new IllegalStateException(MDC_APAPTER_CANNOT_BE_NULL_MESSAGE);
|
||||||
|
}
|
||||||
|
return mdcAdapter.getCopyOfDequeByKey(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
public class BasicMDCAdapter implements MDCAdapter {
|
public class BasicMDCAdapter implements MDCAdapter {
|
||||||
|
|
||||||
private final ThreadLocalMapOfStacks threadLocalMapOfStacks = new ThreadLocalMapOfStacks();
|
private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks();
|
||||||
|
|
||||||
private final InheritableThreadLocal<Map<String, String>> inheritableThreadLocalMap = new InheritableThreadLocal<Map<String, String>>() {
|
private final InheritableThreadLocal<Map<String, String>> inheritableThreadLocalMap = new InheritableThreadLocal<Map<String, String>>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -151,16 +151,20 @@ public class BasicMDCAdapter implements MDCAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushByKey(String key, String value) {
|
public void pushByKey(String key, String value) {
|
||||||
threadLocalMapOfStacks.pushByKey(key, value);
|
threadLocalMapOfDeques.pushByKey(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String popByKey(String key) {
|
public String popByKey(String key) {
|
||||||
return threadLocalMapOfStacks.popByKey(key);
|
return threadLocalMapOfDeques.popByKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Deque<String> getCopyOfStackByKey(String key) {
|
public Deque<String> getCopyOfDequeByKey(String key) {
|
||||||
return threadLocalMapOfStacks.getCopyOfStackByKey(key);
|
return threadLocalMapOfDeques.getCopyOfDequeByKey(key);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void clearDequeByKey(String key) {
|
||||||
|
threadLocalMapOfDeques.clearDequeByKey(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,11 @@ public class NOPMDCAdapter implements MDCAdapter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Deque<String> getCopyOfStackByKey(String key) {
|
public Deque<String> getCopyOfDequeByKey(String key) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearDequeByKey(String key) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,14 @@ import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple implementation of ThreadLocal backed Map containing values of type
|
||||||
|
* Deque<String>.
|
||||||
|
*
|
||||||
|
* @author Ceki Guuml;cü
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
public class ThreadLocalMapOfStacks {
|
public class ThreadLocalMapOfStacks {
|
||||||
|
|
||||||
final ThreadLocal<Map<String, Deque<String>>> tlMapOfStacks = new ThreadLocal<>();
|
final ThreadLocal<Map<String, Deque<String>>> tlMapOfStacks = new ThreadLocal<>();
|
||||||
|
|
@ -20,12 +28,12 @@ public class ThreadLocalMapOfStacks {
|
||||||
tlMapOfStacks.set(map);
|
tlMapOfStacks.set(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
Deque<String> stack = map.get(key);
|
Deque<String> deque = map.get(key);
|
||||||
if (stack == null) {
|
if (deque == null) {
|
||||||
stack = new ArrayDeque<>();
|
deque = new ArrayDeque<>();
|
||||||
}
|
}
|
||||||
stack.push(value);
|
deque.push(value);
|
||||||
map.put(key, stack);
|
map.put(key, deque);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String popByKey(String key) {
|
public String popByKey(String key) {
|
||||||
|
|
@ -35,24 +43,44 @@ public class ThreadLocalMapOfStacks {
|
||||||
Map<String, Deque<String>> map = tlMapOfStacks.get();
|
Map<String, Deque<String>> map = tlMapOfStacks.get();
|
||||||
if (map == null)
|
if (map == null)
|
||||||
return null;
|
return null;
|
||||||
Deque<String> stack = map.get(key);
|
Deque<String> deque = map.get(key);
|
||||||
if (stack == null)
|
if (deque == null)
|
||||||
return null;
|
return null;
|
||||||
return stack.pop();
|
return deque.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Deque<String> getCopyOfStackByKey(String key) {
|
public Deque<String> getCopyOfDequeByKey(String key) {
|
||||||
if (key == null)
|
if (key == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Map<String, Deque<String>> map = tlMapOfStacks.get();
|
Map<String, Deque<String>> map = tlMapOfStacks.get();
|
||||||
if (map == null)
|
if (map == null)
|
||||||
return null;
|
return null;
|
||||||
Deque<String> stack = map.get(key);
|
Deque<String> deque = map.get(key);
|
||||||
if (stack == null)
|
if (deque == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return new ArrayDeque<String>(stack);
|
return new ArrayDeque<String>(deque);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the deque(stack) referenced by 'key'.
|
||||||
|
*
|
||||||
|
* @param key identifies the stack
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public void clearDequeByKey(String key) {
|
||||||
|
if (key == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Map<String, Deque<String>> map = tlMapOfStacks.get();
|
||||||
|
if (map == null)
|
||||||
|
return;
|
||||||
|
Deque<String> deque = map.get(key);
|
||||||
|
if (deque == null)
|
||||||
|
return;
|
||||||
|
deque.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,8 @@ public interface MDCAdapter {
|
||||||
public void setContextMap(Map<String, String> contextMap);
|
public void setContextMap(Map<String, String> contextMap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push a value into the stack referenced by 'key'.
|
* Push a value into the deque(stack) referenced by 'key'.
|
||||||
* *
|
*
|
||||||
* @param key identifies the appropriate stack
|
* @param key identifies the appropriate stack
|
||||||
* @param value the value to push into the stack
|
* @param value the value to push into the stack
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
|
|
@ -104,19 +104,30 @@ public interface MDCAdapter {
|
||||||
/**
|
/**
|
||||||
* Pop the stack referenced by 'key' and return the value possibly null.
|
* Pop the stack referenced by 'key' and return the value possibly null.
|
||||||
*
|
*
|
||||||
* @param key identifies the stack
|
* @param key identifies the deque(stack)
|
||||||
* @return the value just popped. May be null/
|
* @return the value just popped. May be null/
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public String popByKey(String key);
|
public String popByKey(String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a copy of the stack referenced by 'key'. May be null.
|
* Returns a copy of the deque(stack) referenced by 'key'. May be null.
|
||||||
*
|
*
|
||||||
* @param key identifies the stack
|
* @param key identifies the stack
|
||||||
* @return copy of stack referenced by 'key'. May be null.
|
* @return copy of stack referenced by 'key'. May be null.
|
||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
public Deque<String> getCopyOfStackByKey(String key);
|
public Deque<String> getCopyOfDequeByKey(String key);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the deque(stack) referenced by 'key'.
|
||||||
|
*
|
||||||
|
* @param key identifies the stack
|
||||||
|
*
|
||||||
|
* @since 2.0.0
|
||||||
|
*/
|
||||||
|
public void clearDequeByKey(String key);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import org.slf4j.spi.MDCAdapter;
|
||||||
|
|
||||||
public class Log4jMDCAdapter implements MDCAdapter {
|
public class Log4jMDCAdapter implements MDCAdapter {
|
||||||
|
|
||||||
private final ThreadLocalMapOfStacks threadLocalMapOfStacks = new ThreadLocalMapOfStacks();
|
private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
if (VersionUtil.getJavaMajorVersion() >= 9) {
|
if (VersionUtil.getJavaMajorVersion() >= 9) {
|
||||||
|
|
@ -113,17 +113,21 @@ public class Log4jMDCAdapter implements MDCAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushByKey(String key, String value) {
|
public void pushByKey(String key, String value) {
|
||||||
threadLocalMapOfStacks.pushByKey(key, value);
|
threadLocalMapOfDeques.pushByKey(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String popByKey(String key) {
|
public String popByKey(String key) {
|
||||||
return threadLocalMapOfStacks.popByKey(key);
|
return threadLocalMapOfDeques.popByKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Deque<String> getCopyOfStackByKey(String key) {
|
public Deque<String> getCopyOfDequeByKey(String key) {
|
||||||
return threadLocalMapOfStacks.getCopyOfStackByKey(key);
|
return threadLocalMapOfDeques.getCopyOfDequeByKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearDequeByKey(String key) {
|
||||||
|
threadLocalMapOfDeques.clearDequeByKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue