slf4j MDC使用
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使用的更多相关文章
- Slf4j MDC 使用和 基于 Logback 的实现分析
前言 如今,在 Java 开发中,日志的打印输出是必不可少的, 关于 有了日志之后,我们就可以追踪各种线上问题.但是,在分布式系统中,各种无关日志穿行其中,导致我们可能无法直接定位整个操作流程.因此 ...
- [转] Slf4j MDC机制
MDC ( Mapped Diagnostic Contexts ),线程安全的诊断日志存放容器. 可用于存放线程的全局日志信息, 通过xml配置后可以打印在日志中,用于日志记录.定位.分析 相关:h ...
- slf4j中的MDC
slf4j中MDC是什么鬼 slf4j除了trace.debug.info.warn.error这几个日志接口外,还可以配合MDC将数据写入日志.换句话说MDC也是用来记录日志的,但它的使用方式与使用 ...
- Slf4j的MDC初尝试
为什么会用到MDC? 本人使用Java两年时间,鉴于经验有限,在开发java后端代码过程中,为了定位问题,希望同一个线程的requestId可以从web层的日志一直输出到dao层,这样使用Linux命 ...
- LogBack sl4j 通过MDC实现日志记录区分用户Session[以Spring mvc为例]
1.首先实现一个interceptor,在请求开始的时候MDC put一个Session标志,interceptor结束的时候remove掉 import javax.servlet.http.H ...
- SLF4J user manual
http://www.slf4j.org/manual.html The Simple Logging Facade for Java (SLF4J) serves as a simple facad ...
- SLF4J warning or error messages and their meanings(转)
The method o.a.commons.logging.impl.SLF4FLogFactory#release was invoked. Given the structure of the ...
- logback输出json格式日志(包括mdc)发送到kafka
1,pom.xml <!-- kafka --> <dependency> <groupId>com.github.danielwegener</groupI ...
- 日志收集(ElasticSearch)串联查询 MDC
之前写过将应用程序或服务程序产生的日志直接写入搜索引擎的博客 其中基本过程就是 app->redis->logstash->elasticsearch 整个链路过程 本来想将re ...
随机推荐
- 睡眠猴子——beta阶段项目总结
Questions: 每个成员在beta 阶段的实践和alpha 阶段有何改进? 团队在beta 阶段吸取了那些alpha 阶段的经验教训? 12 条敏捷开发的原则中, 团队做得最好和最不好的各列 ...
- PAT 甲级 1022 Digital Library
https://pintia.cn/problem-sets/994805342720868352/problems/994805480801550336 A Digital Library cont ...
- [51CTO]区块链在美国:10个案例、10个问题和5个解决方案
区块链在美国:10个案例.10个问题和5个解决方案 近日,美国国际战略研究中心(CSIS, Center for Strategic and International Studies)发布报告< ...
- 深入理解ajax系列第六篇——头部信息
前面的话 每个HTTP请求和响应都会带有相应的头部信息,其中有的对开发人员有用.XHR对象提供了操作头部信息的方法.本文将详细介绍HTTP的头部信息 默认信息 默认情况下,在发送XHR请求的同时,还会 ...
- linux运行sh文件提示 permission denied
原因:文件没权限 解决:chmod +x 文件名 赋予执行权限或者 chmod 777 文件(赋予最高权限)
- 【题解】 bzoj1207: [HNOI2004]打鼹鼠 (动态规划)
bzoj1207,懒得复制,戳我戳我 Solution: 挺傻逼的一个\(dp\),直接推就好了 这题在bzoj上的数据有点问题,题目保证每个时间点不会出现在同一位置两个地鼠,然而他有= =(还浪费我 ...
- 【题解】 [ZJOI2009]假期的宿舍 (二分图匹配)
懒得复制题面,戳我 Solution: 处理出床位.要留校的人(注意来访问的人一定住校),和人与人的关系(连边) 再接着就是二分图. 注意的就是连向的人必须是有床位的 还要注意的就是只用判断住校的同学 ...
- 【BZOJ1293】[SCOI2009]生日礼物(单调队列)
[BZOJ1293][SCOI2009]生日礼物(单调队列) 题面 BZOJ 洛谷 题解 离散之后随便拿单调队列维护一下就好了. #include<iostream> #include&l ...
- 2019.3.16 noiac的原题模拟赛
RT,这太谔谔了,我不承认这是模拟赛 但是虽然是搬了三道题,题目本身也还能看,就这么着吧 (怎么机房里就我一道原题都没做过啊 T1 CF24D Broken Robot 比较简单地列出式子之后,我们发 ...
- Java: 扩大字节缓存区的大小,提升AIO的处理性能(并发性能)
前些日了,对AIO与NIO的并发性能进行了比较,在低并发的情况下,NIO性能表现比AIO好一些,主要原因是,NIO中可以使用FileChannel.transferTo(long position, ...