正文
利用Slf4j的MDC跟踪方法调用链
顶
原
荐
字数 778
阅读 4
收藏 0
starry SLF4J
参与百度AI开发者大赛赢75万奖金+25万奖品,(提供教程)加群:418589053 >>>
一个web项目通常提供很多URL访问地址,
项目一般都是分层处理,例如Controller——>Service——>DAO。
如果想根据日志查看用户一次请求都走了哪些方法(多数是查错误)。
如果系统是多人访问,日志打印是无序的,想要串行拿到日志是大海捞针。
能通过一个字符串就能将一次请求调用了哪些方法按照顺序搜索出来就好了。
Slf4j的MDC ( Mapped Diagnostic Contexts )专门为此需求而生。
MDC的基本原理是:
通过一个ThreadLocal保存设置的key值,在打印的时候从ThreadLocal中获取到打印出来。由此可知,如果一个请求中的某些方法调用是在另外的线程中执行,那MDC是获取不到该值的。
只需要在日志配置文件的pattern中中添加一个{key},在请求方法入口设置一个key=某字符串,logger日志就能输出此字符串。logger的所有日志方法不需要做任何改动。如下所示。
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{ISO8601} [%thread] [%-5level] [%-10X{tracing_id}] %logger - %msg%n</pattern> </layout> </appender> <!-- 文件输出日志 (文件大小策略进行文件输出,超过指定大小对文件备份)--> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>/data/rec_loader/logs/rec_loader.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>/data/rec_loader/logs/rec_loader.log.%d{yyyy-MM-dd}.%d{hh-mm-ss} </fileNamePattern> <maxHistory>7</maxHistory> <totalSizeCap>100GB</totalSizeCap> </rollingPolicy> <layout class="ch.qos.logback.classic.PatternLayout"> <!--** 改动在此处 tracing_id**--> <Pattern>%d{ISO8601} [%thread] [%-5level] [%-10X{tracing_id}] %logger - %msg%n</Pattern> </layout> </appender> <root level="info"> <appender-ref ref="STDOUT"/> <appender-ref ref="FILE"/> </root> </configuration>
import java.util.Objects; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.MDC; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; /* * * * Starry Starry Night * * __ __ * * //---// * * ). .( * * ( (") ) * * ) ( * * / / * * ( )`` * * ( / /-/ / ) * * w'W W'w * * * author 杨春炼 * email qdcccc@gmail.com * date 2018-08-18 * */ @Slf4j public class ResponseMetricsInterceptor extends HandlerInterceptorAdapter { private static final String TRACING_ID = "tracing_id"; private static final String RESPONSE_TIME = "response_time"; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String tracingId; //this judgement used for webs context if (StringUtils.isBlank(request.getHeader(TRACING_ID))) { tracingId = RandomStringUtils.randomAlphanumeric(10); } else { tracingId = request.getHeader(TRACING_ID); } response.setHeader(TRACING_ID, tracingId); //add a start time in request attribute request.setAttribute(RESPONSE_TIME, System.currentTimeMillis()); MDC.put(TRACING_ID, tracingId); log.info("tracing.start.url={}", request.getServletPath()); return super.preHandle(request, response, handler); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { try { Object attribute = request.getAttribute(RESPONSE_TIME); Long timeStart = Long.valueOf(Objects.toString(attribute, "0")); long responseTime = System.currentTimeMillis() - timeStart; log.info("tracing.end.url={}, 消耗时间:{}ms", request.getServletPath(), responseTime); } catch (Exception ignored) { } finally { //prevent memory leak MDC.remove(TRACING_ID); } super.afterCompletion(request, response, handler, ex); } }
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /* * * * Starry Starry Night * * __ __ * * //---// * * ). .( * * ( (") ) * * ) ( * * / / * * ( )`` * * ( / /-/ / ) * * w'W W'w * * * author 杨春炼 * email qdcccc@gmail.com * date 2018-08-18 * */ @Configuration public class InterceptorConfig extends WebMvcConfigurationSupport { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ResponseMetricsInterceptor()).addPathPatterns("/**"); } }
向自己的项目发起一次http请求
结果如下图(顺便打印了该次http请求的总耗时)
可以自行搜索 SOFATracer,比较重,觉得一般企业没必要应用。
© 著作权归作者所有
共有人打赏支持
粉丝 9
博文 60
码字总数 32724
作品 0
海淀
高级程序员
相关文章 最新文章
SOFATracer 是一个用于分布式系统调用跟踪的组件,通过统一的 将调用链路中的各种网络调用情况以日志的方式记录下来,以达到透视化网络调用的目的。这些日志可用于故障的快速发现,服务治理等...
匿名
05/31
0
0
SLF4J :JAVA简易日志门面(Simple Logging Facade for Java,缩写SLF4J) 他是一套包装Logging 框架的接口程式,以外观模式实现。可在软件部署的时候决定要使用的 Logging 框架,目前主要支援...
Candy_Desire
2014/03/19
0
0
common-logging common-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,...
五大三粗
2015/11/04
0
0
common-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动...
凯文加内特
2015/05/08
0
0
Spring Framework 一直以来都是依赖 commons-logging,通过在 Maven pom.xml 进行配置,可以让 Spring Framework 依赖于越来越流行的 SLF4J,这是利用了 slf4j.org 提供的 jcl-over-slf4j 把...
张前程
2013/12/30
0
0
没有更多内容
加载失败,请刷新页面
加载更多下一页
1. topFlag=topFlag ==0?1:0; 等于 if(topFlag=00){ topFlag=1; }else if(topFlag == 1){ topFlag=0; } 2. 5>3?alert('5大'):alert('3大'); 即 if(5>3){alert('5大')}else{alert('3大')}; 注......
森火
43分钟前
0
0
why? 一个web项目通常提供很多URL访问地址, 项目一般都是分层处理,例如Controller——>Service——>DAO。 如果想根据日志查看用户一次请求都走了哪些方法(多数是查错误)。 如果系统是多人...
杨春炼
50分钟前
4
0
Maven介绍及安装 以下内容是本人早期学习时的笔记,可能比较详实繁琐,现在复习一下Maven,顺便将内容抛出来,供大家一起学习进步。 一、Maven简介 Maven是Apache旗下的一款项目管理工具,是...
星汉
51分钟前
0
0
主要步骤: 1、下载AES源码(JS版) 2、在小程序中新建一个公共的文件夹,把AES源码拷贝进去(注意:需要暴露接口 module.exports = CryptoJS;) 3、添加一个用于加密解密的公共JS,可取名为...
Mr_Tea伯奕
58分钟前
0
0
发送端 package mainimport ("fmt""os""net""io")func SendFile(path string, connect net.Conn){file, oerr :=os.Open(path)if oerr !=nil{fmt.Println("Open", oerr)......
CHONGCHEN
今天
2
0
没有更多内容
加载失败,请刷新页面
加载更多下一页