Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pluggable MDC support #355

Merged
merged 1 commit into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions core/src/main/java/org/jboss/logmanager/ExtLogRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ public void copyAll() {
*/
public void copyMdc() {
if (mdcCopy == null) {
mdcCopy = MDC.fastCopyObject();
mdcCopy = FastCopyHashMap.of(MDC.getMDCProvider().copyObject());
}
}

Expand All @@ -228,9 +228,7 @@ public String getMdc(String key) {
* @return a copy of the MDC map
*/
public Map<String, String> getMdcCopy() {
if (mdcCopy == null) {
mdcCopy = MDC.fastCopyObject();
}
copyMdc();
// Create a new map with string values
final FastCopyHashMap<String, String> newMdc = new FastCopyHashMap<String, String>();
for (Map.Entry<String, Object> entry : mdcCopy.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,14 @@ public Collection<V> values()
return values;
}

public static <K, V> FastCopyHashMap<K, V> of(Map<K, V> map) {
if (map instanceof FastCopyHashMap) {
return (FastCopyHashMap<K, V>) map;
} else {
return new FastCopyHashMap<>(map);
}
}

@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException
{
Expand Down
80 changes: 36 additions & 44 deletions core/src/main/java/org/jboss/logmanager/MDC.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,42 @@

package org.jboss.logmanager;

import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;

/**
* Mapped diagnostic context. This is a thread-local map used to hold loggable information.
*/
public final class MDC {
private static final MDCProvider mdcProvider = getDefaultMDCProvider();

private MDC() {}

private static final Holder mdc = new Holder();
static MDCProvider getMDCProvider() {
return mdcProvider;
}

private static MDCProvider getDefaultMDCProvider() {
return System.getSecurityManager() == null ? doGetDefaultMDCProvider() : AccessController.doPrivileged((PrivilegedAction<MDCProvider>) MDC::doGetDefaultMDCProvider);
}

private static MDCProvider doGetDefaultMDCProvider() {
final ServiceLoader<MDCProvider> configLoader = ServiceLoader.load(MDCProvider.class, MDC.class.getClassLoader());
final Iterator<MDCProvider> iterator = configLoader.iterator();
for (;;) try {
if (! iterator.hasNext()) {
return new ThreadLocalMDC();
}
return iterator.next();
} catch (ServiceConfigurationError | RuntimeException e) {
System.err.print("Warning: failed to load MDC Provider: ");
e.printStackTrace(System.err);
}
}

/**
* Get the value for a key, or {@code null} if there is no mapping.
Expand All @@ -37,8 +63,7 @@ private MDC() {}
* @return the value
*/
public static String get(String key) {
final Object value = getObject(key);
return value == null ? null : value.toString();
return mdcProvider.get(key);
}

/**
Expand All @@ -48,7 +73,7 @@ public static String get(String key) {
* @return the value
*/
public static Object getObject(String key) {
return mdc.get().get(key);
return mdcProvider.getObject(key);
}

/**
Expand All @@ -59,8 +84,7 @@ public static Object getObject(String key) {
* @return the old value or {@code null} if there was none
*/
public static String put(String key, String value) {
final Object oldValue = putObject(key, value);
return oldValue == null ? null : oldValue.toString();
return mdcProvider.put(key, value);
}

/**
Expand All @@ -71,13 +95,7 @@ public static String put(String key, String value) {
* @return the old value or {@code null} if there was none
*/
public static Object putObject(String key, Object value) {
if (key == null) {
throw new NullPointerException("key is null");
}
if (value == null) {
throw new NullPointerException("value is null");
}
return mdc.get().put(key, value);
return mdcProvider.putObject(key, value);
}

/**
Expand All @@ -87,8 +105,7 @@ public static Object putObject(String key, Object value) {
* @return the old value or {@code null} if there was none
*/
public static String remove(String key) {
final Object oldValue = removeObject(key);
return oldValue == null ? null : oldValue.toString();
return mdcProvider.remove(key);
}

/**
Expand All @@ -98,7 +115,7 @@ public static String remove(String key) {
* @return the old value or {@code null} if there was none
*/
public static Object removeObject(String key) {
return mdc.get().remove(key);
return mdcProvider.removeObject(key);
}

/**
Expand All @@ -107,15 +124,7 @@ public static Object removeObject(String key) {
* @return a copy of the map
*/
public static Map<String, String> copy() {
return fastCopy();
}

static FastCopyHashMap<String, String> fastCopy() {
final FastCopyHashMap<String, String> result = new FastCopyHashMap<String, String>();
for (Map.Entry<String, Object> entry : mdc.get().entrySet()) {
result.put(entry.getKey(), entry.getValue().toString());
}
return result;
return mdcProvider.copy();
}

/**
Expand All @@ -124,30 +133,13 @@ static FastCopyHashMap<String, String> fastCopy() {
* @return a copy of the map
*/
public static Map<String, Object> copyObject() {
return fastCopyObject();
}

static FastCopyHashMap<String, Object> fastCopyObject() {
return mdc.get().clone();
return mdcProvider.copyObject();
}

/**
* Clear the current MDC map.
*/
public static void clear() {
mdc.get().clear();
}

private static final class Holder extends InheritableThreadLocal<FastCopyHashMap<String, Object>> {

@Override
protected FastCopyHashMap<String, Object> childValue(final FastCopyHashMap<String, Object> parentValue) {
return new FastCopyHashMap<String, Object>(parentValue);
}

@Override
protected FastCopyHashMap<String, Object> initialValue() {
return new FastCopyHashMap<String, Object>();
}
mdcProvider.clear();
}
}
76 changes: 76 additions & 0 deletions core/src/main/java/org/jboss/logmanager/MDCProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.jboss.logmanager;

import java.util.Map;

public interface MDCProvider {

/**
* Get the value for a key, or {@code null} if there is no mapping.
*
* @param key the key
* @return the value
*/
String get(String key);

/**
* Get the value for a key, or {@code null} if there is no mapping.
*
* @param key the key
* @return the value
*/
Object getObject(String key);

/**
* Set the value of a key, returning the old value (if any) or {@code null} if there was none.
*
* @param key the key
* @param value the new value
* @return the old value or {@code null} if there was none
*/
String put(String key, String value);

/**
* Set the value of a key, returning the old value (if any) or {@code null} if there was none.
*
* @param key the key
* @param value the new value
* @return the old value or {@code null} if there was none
*/
Object putObject(String key, Object value);

/**
* Remove a key.
*
* @param key the key
* @return the old value or {@code null} if there was none
*/
String remove(String key);

/**
* Remove a key.
*
* @param key the key
* @return the old value or {@code null} if there was none
*/
Object removeObject(String key);

/**
* Get a copy of the MDC map. This is a relatively expensive operation.
*
* @return a copy of the map
*/
Map<String, String> copy();

/**
* Get a copy of the MDC map. This is a relatively expensive operation.
*
* @return a copy of the map
*/
Map<String, Object> copyObject();

/**
* Clear the current MDC map.
*/
void clear();

}
78 changes: 78 additions & 0 deletions core/src/main/java/org/jboss/logmanager/ThreadLocalMDC.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.jboss.logmanager;

import java.util.Map;

final class ThreadLocalMDC implements MDCProvider {
private static final Holder mdc = new Holder();

@Override
public String get(String key) {
final Object value = getObject(key);
return value == null ? null : value.toString();
}

@Override
public Object getObject(String key) {
return mdc.get().get(key);
}

@Override
public String put(String key, String value) {
final Object oldValue = putObject(key, value);
return oldValue == null ? null : oldValue.toString();
}

@Override
public Object putObject(String key, Object value) {
if (key == null) {
throw new NullPointerException("key is null");
}
if (value == null) {
throw new NullPointerException("value is null");
}
return mdc.get().put(key, value);
}

@Override
public String remove(String key) {
final Object oldValue = removeObject(key);
return oldValue == null ? null : oldValue.toString();
}

@Override
public Object removeObject(String key) {
return mdc.get().remove(key);
}

@Override
public Map<String, String> copy() {
final FastCopyHashMap<String, String> result = new FastCopyHashMap<>();
for (Map.Entry<String, Object> entry : mdc.get().entrySet()) {
result.put(entry.getKey(), entry.getValue().toString());
}
return result;
}

@Override
public Map<String, Object> copyObject() {
return mdc.get().clone();
}

@Override
public void clear() {
mdc.get().clear();
}

private static final class Holder extends InheritableThreadLocal<FastCopyHashMap<String, Object>> {

@Override
protected FastCopyHashMap<String, Object> childValue(final FastCopyHashMap<String, Object> parentValue) {
return new FastCopyHashMap<>(parentValue);
}

@Override
protected FastCopyHashMap<String, Object> initialValue() {
return new FastCopyHashMap<>();
}
}
}