SLF4J put and immediate get is failing

二次信任 提交于 2020-12-13 04:53:29

问题


I've written a little wrapper for SLF4J MDC.

import org.slf4j.MDC;

import java.util.UUID;


public final class MdcWrapperUtility {



    public static final String MDC_TRANSACTION_ID_KEY_NAME = "MDC_TRANSACTION_ID";

    private MdcWrapperUtility() {
    }

    public static String getId() {
        String threadName = Thread.currentThread().getName();
        String returnValue = MDC.get(MDC_TRANSACTION_ID_KEY_NAME);
        return returnValue;
    }

    public static String setId() {
        String threadName = Thread.currentThread().getName();
        String uuid = UUID.randomUUID().toString();
        String setAndReturnValue = threadName + uuid;
        MDC.put(MDC_TRANSACTION_ID_KEY_NAME, setAndReturnValue);

        String sanityCheck = MDC.get(MDC_TRANSACTION_ID_KEY_NAME);
        if (null == sanityCheck || sanityCheck.length() <= 0)
        {
            throw new NullPointerException("MDC did not persist. How is this even happening?????");
        }

        return setAndReturnValue;
    }
}

At first, after I called "setId()"...i would later call "getId" and it would be null. You can see that I DID verify the thread names...understanding "the thread" is the "magic" that allows MDC to work.

So then I did an MDC.get IMMEDIATELY after the MDC.put, and it is coming back as null.

???

Gaaa.

In my proof of concept project I have:

implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion
implementation group: 'org.slf4j', name: 'slf4j-simple', version: slf4jSimpleVersion

Exact versions below:

    slf4jSimpleVersion = '1.7.30'
    slf4jVersion = '1.7.30'

Both proof-of-concept and "real" give me a null MDC.get (aka, I get the "MDC did not persist. How is this even happening?????" exception.

The only other clue I can offer is that I do NOT have a monolith. I have a multi module gradle project.

https://docs.gradle.org/current/userguide/multi_project_builds.html

I am using variables (defined in my root build.gradle) for my versions, so I do not have a mismatch version in any module(s).

APPEND ONE:

Ok, so I know why it is returning "null". It is using the concrete

public class NOPMDCAdapter implements MDCAdapter {

    public void clear() {
    }

    public String get(String key) {
        return null;
    }

    public void put(String key, String val) {
    }

    public void remove(String key) {
    }

    public Map<String, String> getCopyOfContextMap() {
        return null;
    }

    public void setContextMap(Map<String, String> contextMap) {
        // NOP
    }

}

.........


回答1:


Ok, I figured it out.

And of course, hindsight is 20/20.

I should have focused more on the "simple" part of "'slf4j-simple'"

That does NOT (really) support MDC, and it goes to the NOPMDCAdapter.

When I add a "real" concrete for SLF4J (like logback), I get "real" MDC functionality.

So remove the "simple" and add a "real" one (like logback)

implementation group: 'ch.qos.logback', name: 'logback-classic', version: logbackClassicVersion
implementation group: 'org.slf4j', name: 'slf4j-api', version: slf4jVersion


    logbackClassicVersion = '1.2.3'

And now I get an MDC with my "get".

The "concrete" MDCAdapter after I add 'logback-classic' reference becomes the below one, which actually works.

public class LogbackMDCAdapter implements MDCAdapter {
}

Important documentation nuggets:

(from http://www.slf4j.org/manual.html )

Mapped Diagnostic Context (MDC) support "Mapped Diagnostic Context" is essentially a map maintained by the logging framework where the application code provides key-value pairs which can then be inserted by the logging framework in log messages. MDC data can also be highly helpful in filtering messages or triggering certain actions.

SLF4J supports MDC, or mapped diagnostic context. If the underlying logging framework offers MDC functionality, then SLF4J will delegate to the underlying framework's MDC. Note that at this time, only log4j and logback offer MDC functionality. If the underlying framework does not offer MDC, for example java.util.logging, then SLF4J will still store MDC data but the information therein will need to be retrieved by custom user code.

Thus, as a SLF4J user, you can take advantage of MDC information in the presence of log4j or logback, but without forcing these logging frameworks upon your users as dependencies.



来源:https://stackoverflow.com/questions/64787265/slf4j-put-and-immediate-get-is-failing

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!