slf4j MDC使用

最近也是在项目代码里发现一个地方有个MDC.put(),忍不住好奇点了进去,于是知道了MDC这个东西,细研究一下,发现还真是个好东西。

MDC解决了什么问题

MDC全名Mapped Diagnostic Contexts,是slf4j提供的一个API,主要功能就是在多线程环境下进行日志调用链路的跟踪,比如在一次事务处理中,会经过多个处理的流程,为了定位问题方便,在每个流程中免不了打印一些日志信息。在线上环境中,最后打出来的日志是很多的,如何定位哪些信息是在同一个线程中打印的呢?MDC很优雅地解决了这个问题。其他的日志框架有没有这个功能我暂时没去研究,对于slf4j(现在应该都会优先用这个吧?),实现了MDC的有logback和log4j,这里暂时以logback为例,更详细的文档见这里

MDC的使用

MDC使用起来还是相当简单的,一个例子就搞定了。

首先配置日志配置文件logback.xml

<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} %X{txId} - %msg%n</pattern>
</encoder>
</appender> <root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>

为了输出很简单的一个配置注意有个占位符txId,这就是我们每次事务处理的id。现在我们模拟多个线程同时处理事务。定义了一次事务处理的流程。

public class TxFlow {
private static final Logger LOGGER = LoggerFactory.getLogger(TxFlow.class); private void prepare() {
LOGGER.info("prepare tx");
} private void handle() {
LOGGER.info("handle tx");
try {
Thread.sleep(new Random().nextInt(4) * 1000);
} catch (InterruptedException ignored) {
}
} private void submit() {
LOGGER.info("submit tx");
} public void run() {
prepare();
handle();
submit();
}
}

对每一次事务处理,我们生成一个事务ID,并put到MDC中去。

public class TxMDC {
private static final Logger LOGGER = LoggerFactory.getLogger(TxMDC.class); public static void main(String[] args) {
LOGGER.info("main thread start");
for (int i = 0; i < 5; i++) {
new Thread(() -> {
MDC.put("txId", UUID.randomUUID().toString());
new TxFlow().run();
}).start();
}
}
}

得到输出如下,这样就很容易根据事务ID将一次事务中各个流程中的日志信息串联起来,便于后期的处理(比如查到一次事务的txId后grep一下txId就把整个处理流程中的日志信息串联起来了)。

13:20:21.581 [main] INFO  i.d.l.TxMDC txId=主线程ID - main thread start
13:20:22.050 [Thread-1] INFO i.d.l.TxFlow txId=c4bd7356-b932-4571-bbad-d450e90de821 - prepare tx
13:20:22.050 [Thread-1] INFO i.d.l.TxFlow txId=c4bd7356-b932-4571-bbad-d450e90de821 - handle tx
13:20:22.050 [Thread-2] INFO i.d.l.TxFlow txId=9ee129de-0dfe-4086-9267-e6868e1478b0 - prepare tx
13:20:22.050 [Thread-2] INFO i.d.l.TxFlow txId=9ee129de-0dfe-4086-9267-e6868e1478b0 - handle tx
13:20:22.052 [Thread-3] INFO i.d.l.TxFlow txId=7971563a-2807-4e1f-bbd9-639a090b5689 - prepare tx
13:20:22.053 [Thread-3] INFO i.d.l.TxFlow txId=7971563a-2807-4e1f-bbd9-639a090b5689 - handle tx
13:20:22.053 [Thread-4] INFO i.d.l.TxFlow txId=5c5656c4-bc7a-4277-be25-2269aee0b54e - prepare tx
13:20:22.053 [Thread-4] INFO i.d.l.TxFlow txId=5c5656c4-bc7a-4277-be25-2269aee0b54e - handle tx
13:20:22.054 [Thread-0] INFO i.d.l.TxFlow txId=ebaa0082-1a19-450d-ba71-679510a2fa92 - prepare tx
13:20:22.054 [Thread-0] INFO i.d.l.TxFlow txId=ebaa0082-1a19-450d-ba71-679510a2fa92 - handle tx
13:20:22.082 [Thread-1] INFO i.d.l.TxFlow txId=c4bd7356-b932-4571-bbad-d450e90de821 - submit tx
13:20:23.055 [Thread-0] INFO i.d.l.TxFlow txId=ebaa0082-1a19-450d-ba71-679510a2fa92 - submit tx
13:20:24.050 [Thread-2] INFO i.d.l.TxFlow txId=9ee129de-0dfe-4086-9267-e6868e1478b0 - submit tx
13:20:25.054 [Thread-3] INFO i.d.l.TxFlow txId=7971563a-2807-4e1f-bbd9-639a090b5689 - submit tx
13:20:25.055 [Thread-4] INFO i.d.l.TxFlow txId=5c5656c4-bc7a-4277-be25-2269aee0b54e - submit tx

MDC的实现原理

slf4j只提供了一个接口,具体的实现在logback和log4j中。不过从上面功能中,我们已经知道MDC记录了是线程上下文,聪明的你肯定已经想到了实现是基于ThreadLocal,事实也如此,有兴趣继续研究代码我就不多说了。

slf4j MDC使用的更多相关文章

  1. Slf4j MDC 使用和 基于 Logback 的实现分析

    前言 如今,在 Java 开发中,日志的打印输出是必不可少的, 关于  有了日志之后,我们就可以追踪各种线上问题.但是,在分布式系统中,各种无关日志穿行其中,导致我们可能无法直接定位整个操作流程.因此 ...

  2. [转] Slf4j MDC机制

    MDC ( Mapped Diagnostic Contexts ),线程安全的诊断日志存放容器. 可用于存放线程的全局日志信息, 通过xml配置后可以打印在日志中,用于日志记录.定位.分析 相关:h ...

  3. slf4j中的MDC

    slf4j中MDC是什么鬼 slf4j除了trace.debug.info.warn.error这几个日志接口外,还可以配合MDC将数据写入日志.换句话说MDC也是用来记录日志的,但它的使用方式与使用 ...

  4. Slf4j的MDC初尝试

    为什么会用到MDC? 本人使用Java两年时间,鉴于经验有限,在开发java后端代码过程中,为了定位问题,希望同一个线程的requestId可以从web层的日志一直输出到dao层,这样使用Linux命 ...

  5. LogBack sl4j 通过MDC实现日志记录区分用户Session[以Spring mvc为例]

    1.首先实现一个interceptor,在请求开始的时候MDC put一个Session标志,interceptor结束的时候remove掉   import javax.servlet.http.H ...

  6. SLF4J user manual

    http://www.slf4j.org/manual.html The Simple Logging Facade for Java (SLF4J) serves as a simple facad ...

  7. SLF4J warning or error messages and their meanings(转)

    The method o.a.commons.logging.impl.SLF4FLogFactory#release was invoked. Given the structure of the ...

  8. logback输出json格式日志(包括mdc)发送到kafka

    1,pom.xml <!-- kafka --> <dependency> <groupId>com.github.danielwegener</groupI ...

  9. 日志收集(ElasticSearch)串联查询 MDC

    之前写过将应用程序或服务程序产生的日志直接写入搜索引擎的博客 其中基本过程就是  app->redis->logstash->elasticsearch 整个链路过程  本来想将re ...

随机推荐

  1. 从C简单程序的汇编代码入手,以理解计算机工作原理。

    贺邦  原创作品转载请注明出处 <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000#/info 知识准备 ...

  2. kali 安装使用 sslocal

    shadowsocks 1.安装 shadowsocks apt-get install python-pip sudo pip install shadowsocks 2.配置 shadowsock ...

  3. Mac用户抓包软件Charles 4.0 破解 以及 抓取Https链接设置

    相信大家曾经都是Window的用户,作为前端哪能没有一款抓包工具,抓包工具可以非常便捷的帮助我们分析接口返回报文数据,快速定位问题. 曾经横扫window用户的Fiddler便是我们的挚爱,然而,作为 ...

  4. Java认识对象

    一.类与对象 java中有基本类型和类类型两个类型系统.Java撰写程序几乎都在使用对象,要产生对象必须先定义类,类是对象的设计图,对象是类的实例 1.定义类 类定义使用的关键词为class,建立实例 ...

  5. 12th final 发布评价 I

    1.  约跑App——nice!:这次使用了摄像进行讲解,相比于上次能够更准确地向大家讲解,整体效果更好了,而且很好地针对同学提出的bug进行修改,能够在并不是很熟悉的领域做到这个程度已经很不容易了, ...

  6. jdk动态代理 要把目标对象 和自己都传进去;以便自己对目标对象的代理

  7. 【设计模式】—— 组合模式Composite

    前言:[模式总览]——————————by xingoo 模式意图 使对象组合成树形的结构.使用户对单个对象和组合对象的使用具有一致性. 应用场景 1 表示对象的 部分-整体 层次结构 2 忽略组合对 ...

  8. 【hdu1542】线段树求矩形面积并

    分割线内容转载自http://hzwer.com/879.html ------------------------------------------------------------------ ...

  9. XStream--java对象与xml形式文件相互转换

    1.pom.xml中添加依赖 <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifa ...

  10. $.AJAX参数提交及后台获取方式

    $.AJAX默认是get方式提交,所以你在后台只能用获取url参数的方式获取,可指定type为post更改提交方式: 在后台可通过Request["控件name/url参数key" ...