当前位置:网站首页>[log framework] add user-defined parameters to the MDC implementation log

[log framework] add user-defined parameters to the MDC implementation log

2022-06-13 07:27:00 Small side good side

1、MDC

MDC(Mapped Diagnostic Contexts) Map debug context , It is mainly used for log link tracking , Dynamically configure some user-defined information , such as requestId、sessionId wait .MDC The container used supports multi-threaded operations , Meet thread safety .

2、log4j2 Realization

Call in code MDC.put

public class Log4j2Test {
    

    private static final Logger log = LoggerFactory.getLogger(Log4j2Test.class);

    public static void main(String[] args) {
    
        log.info("test");
        MDC.put("username", "test123");
        log.info("hello world");
    }
}

log4j2.properties in ,pattern increase [%X{username}]
 Insert picture description here
effect :
 Insert picture description here

3、logback Realization

Again java Call in code MDC.put

public class LogbackTest {
    

    private static final Logger log = LoggerFactory.getLogger(LogbackTest.class);

    public static void main(String[] args) {
    
        MDC.put("custom1", "test122");
        log.info("logback test1234-----------------------");
    }
}

logback.xml Add custom parameters in
 Insert picture description here
effect :
 Insert picture description here

4、org.slf4j.MDC

org.slf4j.MDC Through interface MDCAdapter To adapt to different logging frameworks ,MDCAdapter Is a singleton object .
 Insert picture description here
Many different implementation classes
 Insert picture description here
LogbackMDCAdapter: Essentially, ThreadLocal<Map<String, String>>

public class LogbackMDCAdapter implements MDCAdapter {
    
    final ThreadLocal<Map<String, String>> copyOnThreadLocal = new ThreadLocal();
    private static final int WRITE_OPERATION = 1;
    private static final int MAP_COPY_OPERATION = 2;
    final ThreadLocal<Integer> lastOperation = new ThreadLocal();
    // ......
    public void put(String key, String val) throws IllegalArgumentException {
    
        if (key == null) {
    
            throw new IllegalArgumentException("key cannot be null");
        } else {
    
            Map<String, String> oldMap = (Map)this.copyOnThreadLocal.get();
            Integer lastOp = this.getAndSetLastOperation(1);
            if (!this.wasLastOpReadOrNull(lastOp) && oldMap != null) {
    
                oldMap.put(key, val);
            } else {
    
                Map<String, String> newMap = this.duplicateAndInsertNewMap(oldMap);
                newMap.put(key, val);
            }

        }
    }    
    // ......
}    

Log4jMDCAdapter

public class Log4jMDCAdapter implements MDCAdapter {
    
    public Log4jMDCAdapter() {
    
    }

    public void put(String key, String val) {
    
        ThreadContext.put(key, val);
    }
    // ......
}    

ThreadContext
 Insert picture description here
 Insert picture description here

DefaultThreadContextMap: and LogbackMDCAdapter equally , In essence ThreadLocal<Map<String, String>>
 Insert picture description here

5、 Test whether the child parent thread can inherit

MDC Bottom use ThreadLocal Realization , Can achieve thread isolation , Great for C/S、B/S Architecture this scenario of opening a thread for each request to process , The processing of each request is a separate thread . But usually complex business needs to be processed asynchronously , During a request processing , Call other services asynchronously , The log in this asynchronous process can also read the parent thread's MDC Do you ? In fact, the child and parent threads add up to a complete processing flow , We need to read the parent thread's in the seed thread MDC.
With log4j2 For example , First, let's take a look at the new thread directly , Whether the parent thread can be read in the new thread MDC

public class Log4j2Test {
    

    private static final Logger log = LoggerFactory.getLogger(Log4j2Test.class);

    public static void main(String[] args) {
    
        log.info("test");
        MDC.put("username", "test123");
        log.info("hello world");
        new Thread(new Runnable() {
    
            public void run() {
    
                log.info("test Runnable");
            }
        }).start();
    }
}

Of course, the results cannot be read across threads username
 Insert picture description here
But since the bottom floor is ThraedLocal, That is, there are ways to use it across threads ,DefaultThreadContextMap Switch in inheritableMap Decide to localMap Can I integrate between child and parent threads
 Insert picture description here
then resources Add profile in directory log4j2.component.properties

isThreadContextMapInheritable=true

When you run it again, you will find that the child thread has successfully read username.
 Insert picture description here
however logback It seems that no such switch has been found . however logback There is also a way to implement the inheritance of child and parent threads , For example, many call chains java client , Use logback You can also implement the inheritance of child and parent threads , For specific solutions, please refer to zipkin Of java The client .

原网站

版权声明
本文为[Small side good side]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202270549071520.html