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. Java实验报告(实验三)

    课程:Java程序设计          班级: 1351 姓名:王玮怡                学号:20135116 成绩:             指导教师:娄嘉鹏       实验日期: ...

  2. kali 安装使用 sslocal

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

  3. DHCP全局配置文件解析

    作用 参数 ddns-update-style  类型 定义DNS服务动态更新的类型,类型包括:none(不支持动态更新), interim (互动更新模式)与ad-hoc(特殊更新模式) allow ...

  4. Software-Defined Networking:A Comprehensive Survey--Day4

    V. ONGOING RESEARCH EFFORTS AND CHALLENGES 这一节主要介绍了对SDN潜力的发挥有着重要推动作用的一些研究成果. A. Switch Designs 目前Ope ...

  5. Beta冲刺——day3

    Beta冲刺--day3 作业链接 Beta冲刺随笔集 github地址 团队成员 031602636 许舒玲(队长) 031602237 吴杰婷 031602220 雷博浩 031602134 王龙 ...

  6. delphi checklistbox用法

    在Delphi中checklistbox中高亮选中(不论是否Checked)能够进行操作么?删除,上下移动等等 删除:CheckListBox.DeleteSelected; 上下移: CheckLi ...

  7. Python Django性能测试与优化指南

    摘要:本文通过一个简单的实例一步一步引导读者对其进行全方位的性能优化.以下是译文. 唐纳德·克努特(Donald Knuth)曾经说过:“不成熟的优化方案是万恶之源.”然而,任何一个承受高负载的成熟项 ...

  8. BZOJ 2879 [Noi2012]美食节 | 费用流 动态开点

    这道题就是"修车"的数据加强版--但是数据范围扩大了好多,应对方法是"动态开点". 首先先把"所有厨师做的倒数第一道菜"和所有菜连边,然后跑 ...

  9. 在Mac上配置全局的Git忽略文件

    现在同时搞着好几个项目,在Xcode.IDEA.Eclipse之间频繁的切换,每个项目的忽略文件列表都不一样,每个项目都有一个.gitignore,甚是麻烦,今天网上拔出来一个设置全局忽略的办法,记录 ...

  10. 函数、可变参数、keyword-only参数、实参解构

    函数的数学定义:y=f(x) ,y是x的函数,x是自变量.y=f(x0, x1, ..., xn) python中的函数: 由函数名称.参数列表.和若干语句组成的语句块构成,完成一定的功能,是组织代码 ...