成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

生產環境定位日志太麻煩怎么辦?建議了解一下日志框架的MDC功能

開發 前端
MDC是日志門面框架SLF4J提供的一個類,可以提供在多線程情況下記錄日志的功能,log4j、logback、log4j2都有對這個類的實現。

對于每一個開發者來說,查詢接口的執行日志都是一個高頻率的操作,每當測試說接口有問題時,我們都需要去服務器或者日志系統上查報錯的原因。
一般情況下,我們會通過對應的關鍵字或者接口地址去查詢這個接口到底報了什么錯,但是這帶來一個問題,就是我們可能少打日志或者忘打某些關鍵字的日志,導致查詢記錄比較麻煩。

那么有沒有一種簡單高效的方法,即使我們在日志中不打印任何關鍵字,系統會自動生成一個關鍵字,讓我們一次性查詢出這個接口的所有log記錄呢?

MDC

MDC是日志門面框架SLF4J提供的一個類,可以提供在多線程情況下記錄日志的功能,log4j、logback、log4j2都有對這個類的實現。

從本質上來說,MDC可以看做一個ThreadLocal,由于其線程安全的特性,可以讓我們輕松安全的保存數據。

MDC主要的API有clear()、get()、put()、remove()方法等,簡潔的api讓我們使用上手基本沒有難度。

如何使用

1、修改日志打印格式

以日志框架logback為例,在logback.xml中,找到日志打印規則的配置,添加-%X{reqId}屬性,其中reqId可以任意指定,你寫其他的屬性也可以,博主這里演示指定為reqId。

<encoder>
<pattern>-%X{reqId} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %file:%line %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>

2、添加過濾器MDCFilter

ps.使用攔截器也可以,效果是一樣的。對每個接口做攔截。

@Component
@AllArgsConstructor
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
public class MDCFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain){
try {
//給每個請求接口生成一個requestId
String requestId = RandomUtil.randomNumbers(10);
//這里的reqId就是上面配置的,要保持一致
MDC.put("reqId", "reqId:" + requestId);
chain.doFilter(request, response);
} finally {
MDC.clear();
}
}

@Override
public void destroy(){
}
}

經過簡單的兩步就配置好了,下面我們看一下效果。

@PostMapping(value = "/mdcTest")
public ResponseEntity<Object> mdcTest(String id, String name) {
log.info("測試日志打印,id={},name={}", id, name);
log.info("測試日志打印1");
log.info("測試日志打印2");
log.info("測試日志打印3");
log.info("測試日志打印4");
return ResponseEntity.ok().build();
}


每一行日志都有一個關鍵字reqId:9723829830,這樣我們查詢日志時只需要查詢關鍵字9723829830就可以直接查出來這個接口所有的執行記錄了。

如果想更方便的話,也可以把這個關鍵字直接輸出到每一個接口的響應頭或者響應體中。

進階使用

對于普通的web應用我們可以直接攔截每個接口,自動生成一個請求id,那么對于微服務項目,一個接口可能會產生很多服務的調用,那如何一次性查出來所有系統內的日志呢?

對于日志的搜集本文暫不考慮,咱們先說如何做請求id的傳遞。

其實也很簡單,當我們有多個系統間的調用時,把reqId放到request的header中進行傳遞,然后下游系統獲取這個id就可以了。

比如下方的攔截器:

public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//如果有上層調用就從header中取出上層的ID
String traceId = request.getHeader("reqId");
if (traceId == null) {
//如果沒有,就生成一個默認的
traceId = RandomUtil.randomNumbers(10);
}
MDC.put("reqId", traceId);
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
//調用結束后刪除
MDC.remove("reqId");
}
}

MDC存在的一些問題

我們在上文說過,MDC的本質是ThreadLocal,它會把數據都綁定到當前線程上。但是當我們使用多線程的時候,就會帶來一個數據丟失的問題。

所以,我們需要進行線程間的數據傳遞,保證MDC數據不丟失。

以線程池傳遞數據為例,ThreadPoolTaskExecutor提供了一個taskDecorator裝飾器,通過這個屬性,我們就可以實現屬性的傳遞。

首先,定義一個MDCContextDecorator。

public class MDCContextDecorator implements TaskDecorator {

@Override
public Runnable decorate(Runnable runnable){
Map<String,String> previous = MDC.getCopyOfContextMap();
return () -> {
try {
if (previous != null) {
MDC.setContextMap(previous);
}
runnable.run();
} finally {
MDC.clear();
}
};
}
}

然后設置線程池的taskDecorator屬性。

public ThreadPoolTaskExecutor executor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(20);
//...其他屬性
//設置線程屬性的自動傳遞
executor.setTaskDecorator(new MDCContextDecorator());
return executor;
}

最后

MDC的使用其實很簡單,對于我們查詢日志也很有幫助,應用也算是非常廣泛了。有興趣的同學也可以去看一下它的內部實現,代碼也并不復雜。

責任編輯:姜華 來源: 今日頭條
相關推薦

2018-12-26 18:05:28

華為云

2020-12-22 09:17:49

日志Loki服務

2023-08-21 11:24:43

AndroidCSS

2025-02-26 08:26:38

2020-11-17 06:42:21

MySQL數據庫開源

2020-02-10 14:26:10

GitHub代碼倉庫

2010-02-26 13:14:39

Java日志系統

2024-09-19 09:30:39

緩存框架抽象

2020-12-10 08:44:35

WebSocket輪詢Comet

2022-03-24 13:36:18

Java悲觀鎖樂觀鎖

2023-01-11 08:09:25

Springboot修改日志級別

2021-04-27 07:52:18

SQLNULLOR

2021-06-29 21:36:21

微服務Nacos日志

2020-03-01 17:53:38

Excel大數據微軟

2022-04-22 10:30:07

框架JavaScript前端

2019-12-02 10:16:45

Linux 開源操作系統

2023-04-23 14:55:10

開發TypeScript裝飾器

2024-09-11 08:10:46

2015-08-26 11:00:42

機房環境

2021-12-07 11:46:33

KubernetesEvicted PodLinux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: a欧美 | 午夜欧美 | 免费毛片www com cn | 中文字幕国产精品视频 | 精品99爱视频在线观看 | 日韩一区二区免费视频 | a国产视频 | 精品欧美一区二区中文字幕视频 | 久久蜜桃av一区二区天堂 | 午夜免费观看网站 | 91高清在线视频 | 91精品综合久久久久久五月天 | 国产精品亚洲精品日韩已方 | 一级毛片在线播放 | 久久99国产精品 | 精品视频一区二区三区在线观看 | 国产高清精品一区二区三区 | 欧美黄在线观看 | 亚洲国产网站 | 久久国内精品 | 亚洲视频在线观看 | 免费亚洲一区二区 | 日韩高清成人 | 国产成人免费视频网站视频社区 | 国产成人综合一区二区三区 | 一区二区三区四区av | www.玖玖玖 | 日本高清精品 | 国产黄色一级片 | 中文字幕在线观看一区二区 | av在线伊人 | 国产一区二区电影 | 欧美女优在线观看 | 欧美福利精品 | 91精品国产自产在线老师啪 | 中文字幕一区二区三区乱码在线 | 免费视频成人国产精品网站 | 一区二区三区高清 | 欧美精品一区二区三区四区 在线 | www狠狠干 | 在线播放91|