All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.qos.logback.classic.util.LogbackMDCAdapter Maven / Gradle / Ivy

The newest version!
/**
 * Logback: the reliable, generic, fast and flexible logging framework.
 * Copyright (C) 1999-2022, QOS.ch. All rights reserved.
 *
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation
 *
 *   or (per the licensee's choosing)
 *
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation.
 */
package ch.qos.logback.classic.util;

import org.slf4j.helpers.ThreadLocalMapOfStacks;
import org.slf4j.spi.MDCAdapter;

import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * A Mapped Diagnostic Context, or MDC in short, is an instrument for
 * distinguishing interleaved log output from different sources. Log output is
 * typically interleaved when a server handles multiple clients
 * near-simultaneously.
 * 

* The MDC is managed on a per thread basis. Note that a child * thread does not inherit the mapped diagnostic context of its parent. *

*

* For more information about MDC, please refer to the online manual at * http://logback.qos.ch/manual/mdc.html * * @author Ceki Gülcü * @author Michael Franz */ public class LogbackMDCAdapter implements MDCAdapter { // BEWARE: Keys or values placed in a ThreadLocal should not be of a type/class // not included in the JDK. See also https://jira.qos.ch/browse/LOGBACK-450 final ThreadLocal> readWriteThreadLocalMap = new ThreadLocal>(); final ThreadLocal> readOnlyThreadLocalMap = new ThreadLocal>(); private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks(); /** * Put a context value (the val parameter) as identified with the * key parameter into the current thread's context map. Note that * contrary to log4j, the val parameter can be null. *

*

* If the current thread does not have a context map it is created as a side * effect of this call. *

*

* Each time a value is added, a new instance of the map is created. This is * to be certain that the serialization process will operate on the updated * map and not send a reference to the old map, thus not allowing the remote * logback component to see the latest changes. * * @throws IllegalArgumentException in case the "key" parameter is null */ public void put(String key, String val) throws IllegalArgumentException { if (key == null) { throw new IllegalArgumentException("key cannot be null"); } Map current = readWriteThreadLocalMap.get(); if (current == null) { current = new HashMap(); readWriteThreadLocalMap.set(current); } current.put(key, val); nullifyReadOnlyThreadLocalMap(); } /** * Get the context identified by the key parameter. *

*

* This method has no side effects. */ @Override public String get(String key) { Map hashMap = readWriteThreadLocalMap.get(); if ((hashMap != null) && (key != null)) { return hashMap.get(key); } else { return null; } } /** *

Remove the context identified by the key parameter. *

*/ @Override public void remove(String key) { if (key == null) { return; } Map current = readWriteThreadLocalMap.get(); if (current != null) { current.remove(key); nullifyReadOnlyThreadLocalMap(); } } private void nullifyReadOnlyThreadLocalMap() { readOnlyThreadLocalMap.set(null); } /** * Clear all entries in the MDC. */ @Override public void clear() { readWriteThreadLocalMap.set(null); nullifyReadOnlyThreadLocalMap(); } /** *

Get the current thread's MDC as a map. This method is intended to be used * internally.

* * The returned map is unmodifiable (since version 1.3.2/1.4.2). */ @SuppressWarnings("unchecked") public Map getPropertyMap() { Map readOnlyMap = readOnlyThreadLocalMap.get(); if (readOnlyMap == null) { Map current = readWriteThreadLocalMap.get(); if (current != null) { final Map tempMap = new HashMap(current); readOnlyMap = Collections.unmodifiableMap(tempMap); readOnlyThreadLocalMap.set(readOnlyMap); } } return readOnlyMap; } /** * Return a copy of the current thread's context map. Returned value may be * null. */ public Map getCopyOfContextMap() { Map readOnlyMap = getPropertyMap(); if (readOnlyMap == null) { return null; } else { return new HashMap(readOnlyMap); } } /** * Returns the keys in the MDC as a {@link Set}. The returned value can be * null. */ public Set getKeys() { Map readOnlyMap = getPropertyMap(); if (readOnlyMap != null) { return readOnlyMap.keySet(); } else { return null; } } @SuppressWarnings("unchecked") public void setContextMap(Map contextMap) { if (contextMap != null) { readWriteThreadLocalMap.set(new HashMap(contextMap)); } else { readWriteThreadLocalMap.set(null); } nullifyReadOnlyThreadLocalMap(); } @Override public void pushByKey(String key, String value) { threadLocalMapOfDeques.pushByKey(key, value); } @Override public String popByKey(String key) { return threadLocalMapOfDeques.popByKey(key); } @Override public Deque getCopyOfDequeByKey(String key) { return threadLocalMapOfDeques.getCopyOfDequeByKey(key); } @Override public void clearDequeByKey(String key) { threadLocalMapOfDeques.clearDequeByKey(key); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy