How to implement log tracking MDC by java
这篇文章主要为大家展示了"java怎么实现日志追踪MDC",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"java怎么实现日志追踪MDC"这篇文章吧。
java 日志追踪MDC
MDC ( Mapped Diagnostic Contexts ) 有了日志之后,我们就可以追踪各种线上问题。
但是,在分布式系统中,各种无关日志穿行其中,导致我们可能无法直接定位整个操作流程。
因此,我们可能需要对一个用户的操作流程进行归类标记,比如使用线程+时间戳,或者用户身份标识等;如此,我们可以从大量日志信息中grep出某个用户的操作流程,或者某个时间的流转记录。其目的是为了便于我们诊断线上问题而出现的方法工具类。
虽然,Slf4j 是用来适配其他的日志具体实现包的,但是针对 MDC功能,目前只有logback 以及 log4j 支持。 MDC
package org.slf4j; import java.io.Closeable;import java.util.Map; import org.slf4j.helpers.NOPMDCAdapter;import org.slf4j.helpers.BasicMDCAdapter;import org.slf4j.helpers.Util;import org.slf4j.impl.StaticMDCBinder;import org.slf4j.spi.MDCAdapter; public class MDC { static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA"; static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder"; static MDCAdapter mdcAdapter; public static class MDCCloseable implements Closeable { private final String key; private MDCCloseable(String key) { this.key = key; } public void close() { MDC.remove(this.key); } } private MDC() { } static { try { mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA(); } catch (NoClassDefFoundError ncde) { mdcAdapter = new NOPMDCAdapter(); String msg = ncde.getMessage(); if (msg != null && msg.indexOf("StaticMDCBinder") != -1) { Util.report("Failed to load class \"org.slf4j.impl.StaticMDCBinder\"."); Util.report("Defaulting to no-operation MDCAdapter implementation."); Util.report("See " + NO_STATIC_MDC_BINDER_URL + " for further details."); } else { throw ncde; } } catch (Exception e) { // we should never get here Util.report("MDC binding unsuccessful.", e); } } public static void put(String key, String val) throws IllegalArgumentException { if (key == null) { throw new IllegalArgumentException("key parameter cannot be null"); } if (mdcAdapter == null) { throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); } mdcAdapter.put(key, val); } public static MDCCloseable putCloseable(String key, String val) throws IllegalArgumentException { put(key, val); return new MDCCloseable(key); } public static String get(String key) throws IllegalArgumentException { if (key == null) { throw new IllegalArgumentException("key parameter cannot be null"); } if (mdcAdapter == null) { throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); } return mdcAdapter.get(key); } public static void remove(String key) throws IllegalArgumentException { if (key == null) { throw new IllegalArgumentException("key parameter cannot be null"); } if (mdcAdapter == null) { throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); } mdcAdapter.remove(key); } public static void clear() { if (mdcAdapter == null) { throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); } mdcAdapter.clear(); } public static Map getCopyOfContextMap() { if (mdcAdapter == null) { throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); } return mdcAdapter.getCopyOfContextMap(); } public static void setContextMap(Map contextMap) { if (mdcAdapter == null) { throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL); } mdcAdapter.setContextMap(contextMap); } public static MDCAdapter getMDCAdapter() { return mdcAdapter; } }简单的demopackage com.alibaba.otter.canal.common; import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.slf4j.MDC; public class LogTest { private static final Logger logger = LoggerFactory.getLogger(LogTest.class); public static void main(String[] args) { MDC.put("THREAD_ID", String.valueOf(Thread.currentThread().getId())); logger.info("纯字符串信息的info级别日志"); }}
logback.xml 配置
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{56} %X{THREAD_ID} - %msg%n