转载

原 荐 利用Slf4j的MDC跟踪方法调用链

杨春炼的个人空间 基础—万丈高楼平地起

正文

原 荐 利用Slf4j的MDC跟踪方法调用链

利用Slf4j的MDC跟踪方法调用链

原 荐 利用Slf4j的MDC跟踪方法调用链
  杨春炼 发布于 50分钟前

字数 778

阅读 4

收藏 0

starry SLF4J

参与百度AI开发者大赛赢75万奖金+25万奖品,(提供教程)加群:418589053 >>> 原 荐 利用Slf4j的MDC跟踪方法调用链

why?

一个web项目通常提供很多URL访问地址,

项目一般都是分层处理,例如Controller——>Service——>DAO。

如果想根据日志查看用户一次请求都走了哪些方法(多数是查错误)。

如果系统是多人访问,日志打印是无序的,想要串行拿到日志是大海捞针。

能通过一个字符串就能将一次请求调用了哪些方法按照顺序搜索出来就好了。

how?

Slf4j的MDC ( Mapped Diagnostic Contexts )专门为此需求而生。

MDC的基本原理是:

通过一个ThreadLocal保存设置的key值,在打印的时候从ThreadLocal中获取到打印出来。由此可知,如果一个请求中的某些方法调用是在另外的线程中执行,那MDC是获取不到该值的。

1 修改日志文件

只需要在日志配置文件的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>

2 增加拦截器(跨系统之间可用,通过增加header字段)

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("/**");
	}
}

Effect

向自己的项目发起一次http请求

结果如下图(顺便打印了该次http请求的总耗时)

原 荐 利用Slf4j的MDC跟踪方法调用链

更专业的分布式链路追踪中间件?

可以自行搜索 SOFATracer,比较重,觉得一般企业没必要应用。

© 著作权归作者所有

共有人打赏支持

原 荐 利用Slf4j的MDC跟踪方法调用链

杨春炼

粉丝 9

博文 60

码字总数 32724

作品 0

海淀

高级程序员

相关文章 最新文章

分布式链路追踪中间件 - SOFATracer

SOFATracer 是一个用于分布式系统调用跟踪的组件,通过统一的 将调用链路中的各种网络调用情况以日志的方式记录下来,以达到透视化网络调用的目的。这些日志可用于故障的快速发现,服务治理等...

匿名

05/31

0

0

比较 SLF4J 与 log4j

SLF4J :JAVA简易日志门面(Simple Logging Facade for Java,缩写SLF4J) 他是一套包装Logging 框架的接口程式,以外观模式实现。可在软件部署的时候决定要使用的 Logging 框架,目前主要支援...

Candy_Desire

2014/03/19

0

0

java日志组件介绍(common-logging,log4j,slf4j,logback)

common-logging common-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,...

五大三粗

2015/11/04

0

0

java日志组件介绍(common-logging,log4j,slf4j,logback )

common-logging是apache提供的一个通用的日志接口。用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动...

凯文加内特

2015/05/08

0

0

让 Spring Framework 依赖 SLF4J 的 Maven 配置

Spring Framework 一直以来都是依赖 commons-logging,通过在 Maven pom.xml 进行配置,可以让 Spring Framework 依赖于越来越流行的 SLF4J,这是利用了 slf4j.org 提供的 jcl-over-slf4j 把...

张前程

2013/12/30

0

0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JS三元运算示例

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

利用Slf4j的MDC跟踪方法调用链

why? 一个web项目通常提供很多URL访问地址, 项目一般都是分层处理,例如Controller——>Service——>DAO。 如果想根据日志查看用户一次请求都走了哪些方法(多数是查错误)。 如果系统是多人...

杨春炼

50分钟前

4

0

原 荐 利用Slf4j的MDC跟踪方法调用链
Maven介绍及安装

Maven介绍及安装 以下内容是本人早期学习时的笔记,可能比较详实繁琐,现在复习一下Maven,顺便将内容抛出来,供大家一起学习进步。 一、Maven简介 Maven是Apache旗下的一款项目管理工具,是...

星汉

51分钟前

0

0

原 荐 利用Slf4j的MDC跟踪方法调用链
小程序Aes解密

主要步骤: 1、下载AES源码(JS版) 2、在小程序中新建一个公共的文件夹,把AES源码拷贝进去(注意:需要暴露接口 module.exports = CryptoJS;) 3、添加一个用于加密解密的公共JS,可取名为...

Mr_Tea伯奕

58分钟前

0

0

Go实现文件传输(基本传输可用)

发送端 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

没有更多内容

加载失败,请刷新页面

加载更多

下一页

原文  https://my.oschina.net/yangchunlian/blog/1929982
正文到此结束
Loading...