开发者

Logback MDCAdapter日志跟踪及自定义效果源码解读

开发者 https://www.devze.com 2023-11-19 12:06 出处:网络 作者: codecraft
目录序MDCAdapterLogbackMDCAdapterreadwriteThreadLocalMapgetCopyOfContextMapthreadLocalMapOfDequesThreadLocalMapOfStacks小结序
目录
  • MDCAdapter
  • LogbackMDCAdapter
    • readwriteThreadLocalMap
    • getCopyOfContextMap
    • threadLocalMapOfDeques
    • ThreadLocalMapOfStacks
  • 小结

    本文主要研究一下LogbackMDCAdapter

    MDCAdapter

    org/slf4j/spi/MDCAdapter.Java

    public interface MDCAdapter {
        /**
         * Put a context value (the <code>val</code> parameter) as identified with
         * the <code>key</code> parameter into the current thread's context map. 
         * The <code>key</code> parameter cannot be null. The <code>val</code> parameter
         * can be null only if the underlying implementation supports it.
         * 
         * <p>If the current thread does not have a context map it is created as a side
         * effect of this call.
         */
        public void put(String key, String val);
        /**
         * Get the context identified by the <code>key</code> pjsarameter.
         * The <code>key</code> parameter cannot be null.
         * 
         * @return the string value identified by the <code>key</code> parameter.
         */
        public String get(String key);
        /**
         * Remove the context identified by the <code>key</code> parameter.
         * The <code>key</code> parameter cannot be null. 
         * 
         * <p>
         * This method does nothing if there is no previous value 
         * associated with <code>key</code>.
         */
        public void remove(String key);
        /**
         * Clear all entries in the MDC.
         */
        public void clear();
        /**
         * Return a copy of the current thread's context map, with keys and 
         * values of type String. Returned value may be null.
         * 
         * @return A copy of the current thread's context map. May be null.
         * @since 1.5.1
         */
        public Map<String, String> getCopyOfContextMap();
        /**
         * Set the current thread's context map by first clearing any existing 
         * map and then copying the map passed as parawww.devze.commeter. The context map 
         * parameter must only contain keys and values of type String.
         * 
         * Implementations must support null valued map passed as parameter.
         * 
         * @param contextMap must contain only keys and values of type String
         * 
         * @since 1.5.1
         */
        public void setContextMap(Map<String, String> contextMap);
        /**
         * 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
         */
        public void pushByKey(String key, String 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
         */
        public String popByKey(String 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);
        /**
         * Clear the deque(stack) referenced by 'key'. 
         * 
         * @param key identifies the  stack
         * 
         * @since 2.0.0
         */
        public void clearDequeByKey(String key);
    }
    slf4j定义了MDCAdapter接口,该接口定义了put、get、remove、clear、getCopyOfContextMap、setContextMap、pushByKey、popByKey、getCopyOfDequeByKey、clearDequeByKey方法

    LogbackMDCAdapter

    ch/qos/logback/classic/util/LogbackMDCAdapter.java

    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<Map<String, String>> readWriteThreadLocalMap = new ThreadLocal<Map<String, String>>();
        final ThreadLocal<Map<String, String>> readOnlyThreadLocalMap = new ThreadLocal<Map<String, String>>();
        private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks();
        //......
    }
    LogbackMDCAdapter实现了MDCAdapter接口,它基于readWriteThreadLocalMap、readOnlyThreadLocalMap、threadLocalMapOfDeques来实现

    readWriteThreadLocalMap

    public void put(String key, String val) throws IllegalArgumentException {
            if (key == null) {
                throw new IllegalArgumentException("key cannot be null");
            }
            Map<String, String> current = readWriteThreadLocalMap.get();
            if (current == null) {
                current = new HashMap<String, String>();
                readWriteThreadLocalMap.set(current);
            }
            current.put(key, val);
            nullifyReadOnlyThreadLocalMap();
        }
        @Override
        public String get(String key) {
            Map<String, String> hashMap = readWriteThreadLocalMap.get();
            if ((hashMap != null) && (key != null)) {
                return hashMap.get(key);
            } else {
                return null;
            }
        }
        @Override
        public void remove(String key) {
            if (key == null) {
                return;
            }
            Map<String, String> current = readWriteThreadLocalMap.get();
            if (current != null) {
                current.remove(key);
                nullifyReadOnlyThreadLocalMap();
            }
        }
        @Override
        public void clear() {
            readWriteThreadLocalMap.set(null);
            nullifyR编程客栈eadOnlyThreadLocalMap();
        }
        private void nullifyReadOnlyThreadLocalMap() {
            readOnlyThreadLocalMap.set(null);
        }  
        public void setContextMap(Map contextMap) {
            if (contextMap != null)编程客栈 {
                readWriteThreadLocalMap.set(new HashMap<String, String>(contextMap));
            } else {
                readWriteThreadLocalMap.set(null);
            }
            nullifyReadOnlyThreadLocalMap();
        }
    put、get、remove、clear、setContextMap都是基于readWriteThreadLocalMap,同时修改操作会同时调用nullifyReadOnlyThreadLocalMap,将readOnlyThreadLocalMap设置为null

    getCopyOfContextMap

    public Map getCopyOfContextMap() {
            Map<String, String> readOnlyMap = getPropertyMap();
            if (readOnlyMap == null) {
                return null;
            } else {
                return new HashMap<String, String>(readOnlyMap);
            }
        }
    
        public Map<String, String> getPropertyMap() {
            Map<String, String> readOnlyMap = readOnlyThreadLocalMap.get();
            if (readOnlyMap == null) {
                Map<String, String> current = readWriteThreadLocalMap.get();
                if (current != null) {
                    final Map<String, String> tempMap = new HashMap<String, String>(current);
                    readOnlyMap = Collections.unmodifiableMap(tempMap);
                    readOnlyThreadLocalMap.set(readOnlyMap);
                }
            }
            return readOnlyMap;
        }
    getCopyOfContextMap方法通过getProTsgwApertyMap获取,如果不为null则新创建HashMap返回;getPropertyMap先从readOnlyThreadLocalMap读取,如果readOnlyThreadLocalMap为null则从readWriteThreadLocalMap拷贝一份unmodifiableMap,并设置到readOnlyThreadLocalMap

    threadLocalMapOfDeques

    @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<String> getCopyOfDequeByKey(String key) {
            return threadLocalMapOfDeques.getCopyOfDequeByKey(key);
        }
        @Override
        public void clearDequeByKey(String key) {
            threadLocalMapOfDeques.clearDequeByKey(key);
        }
    pushByKey、popByKey、getCopyOfDequeByKey、clearDequeByKey均是基于threadLocalMapOfDeques,它是ThreadLocalMapOfStacks类型

    ThreadLocalMapOfStacks

    org/slf4j/helpers/ThreadLocalMapOfStacks.java

    public class ThreadLocalMapOfStacks {
        // 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<Map<String, Deque<String>>> tlMapOfStacks = new ThreadLocal<>();
        public void pushByKey(String key, String value) {
            if (key == null)
                return;
            Map<String, Deque<String>> map = tlMapOfStacks.get();
            if (map == null) {
                map = new HashMap<>();
                tlMapOfStacks.set(map);
            }
            Deque<String> deque = map.get(key);
            if (deque == null) {
                deque = new ArrayDeque<>();
            }
            deque.push(value);
            map.put(key, deque);
        }
        public String popByKey(String key) {
            if (key == null)
                return null;
            Map<String, Deque<String>> map = tlMapOfStacks.get();
            if (map == null)
                return null;
            Deque<String> deque = map.get(key);
            if (deque == null)
                return null;
            return deque.pop();
        }
        public Deque<String> getCopyOfDequeByKey(String key) {
            if (key == null)
                return null;
            Map<String, Deque<String>> map = tlMapOfStacks.get();
            if (map == null)
                return null;
            Deque<String> deque = map.get(key);
            if (deque == null)
                return null;
            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();
        }
    }
    ThreadLocalMapOfStacks是slf4j定义的,基于ThreadLocal<Map<String, Deque<String>>>实现的

    小结

    slf4j定义了MDCAdapter接口,该接口定义了put、get、remove、clear、getCopyOfContextMap、setContextMap、pushByKey、popByKey、getCopyOfDequeByKey、clearDequeByKey方法;LogbackMDCAdapter实现了MDCAdapter接口,它基于readWriteThreadLocalMap、readOnlyThreadLocalMap、threadLocalMapOfDeques来实现,其中put、get、remove、clear、setContextMap都是基于readWriteThreadLocalMap,pushByKey、popByKey、getCopyOfDequeByKey、clearDequeByKey均是基于threadLocalMapOfDeques。

    以上就是Logback MDCAdapter日志跟踪及自定义效果源码解读的详细内容,更多关于Logback MDCAdapter日志跟踪的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消