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

Java Web中日志跟蹤的簡單實現

開發 前端
MDC(Mapped Diagnostic Context,映射調試上下文)是 log4j 、logback及log4j2 提供的一種方便在多線程條件下記錄日志的功能。MDC 可以看成是一個與當前線程綁定的哈希表,MDC 中包含的內容可以被同一線程中執行的代碼所訪問。

一、前言

在編碼過程中,常常需要寫打印日志語句,我們期望的是同一個業務的日志都在一塊,在出問題的時候好根據日志來排查問題。而現實是在應用運行中,日志的輸出常常來自不同線程,甚至是在不同微服務中,各種日志記錄往往彼此穿插,很難串起來。所以往往在日志中手動增加一些關鍵字,來對接口的調用鏈路來進行跟蹤。但這種手動增加關鍵字或唯一標識的做法在微服務場景下,很難在上下游應用的開發人員的編碼風格形成統一的規范,并且手動編寫也很難稱得上優雅。

二、MDC介紹

MDC(Mapped Diagnostic Context,映射調試上下文)是 log4j 、logback及log4j2 提供的一種方便在多線程條件下記錄日志的功能。MDC 可以看成是一個與當前線程綁定的哈希表,MDC 中包含的內容可以被同一線程中執行的代碼所訪問。

MDC中的鍵值對是可以直接被日志框架所使用(即“打印”)的,只需要配置相應日志pattern。例如pattern如下:

%d{HH:mm:ss.SSS} [%thread] [%X{TraceId}] %-5level %logger{50} - %msg%n

代碼如下:

public class MDCTest {

private static final Logger log = LoggerFactory.getLogger(MDCTest.class);

@Test
void test() {
MDC.put("TraceId", "123456789");
log.info("hello {}", "world");
}
}

此時控制臺將輸出:

21:16:04.342 [main] [123456789] INFO  com.nk.MDCTest - hello world

三、實現方案

1、基本思路

修改日志pattern,并在業務開始的時候將trace id放入到MDC,在業務結束時去除MDC的trace id。這樣的好處便是代碼簡潔,不需要手動寫trace id,日志風格也能保持統一。

業務開始的時機一般是應用收到HTTP請求,所以可以用Filter或SpringMVC的Interceptor來對MDC中trace id進行初始化和清除。在Dubbo調用的時候也可以通過類似功能的Filter來對MDC中trace id進行操作,從而達到trace id傳遞的作用。

2、實現(以SpringBoot為例)

2.1 修改log pattern

在SpringBoot中,直接修改application.properties即可:

logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{TraceId}] %-5level %logger{50} - %msg%n

重點在于%X{TraceId},其中TraceId需要作為key出現在MDC里。

2.1.1 業務開始

TraceId工具類,封裝MDC關于trace id的基礎操作:

public final class TraceIdUtil {

private static final String TRACE_ID_KEY = "TraceId";

private TraceIdUtil() {
}

public static void putIfAbsent() {
if (StrUtil.isBlank(get())) {
put(UUID.randomUUID().toString());
}
}

public static void remove() {
if (get() != null) {
MDC.remove(TRACE_ID_KEY);
}
}

public static String get() {
return MDC.get(TRACE_ID_KEY);
}

public static void put(String traceId) {
MDC.put(TRACE_ID_KEY, traceId);
}
}

Filter方式和Interceptor二選其一既可,其基本思想是一樣的。

Filter方式

@Component
public class LogFilter implements Filter {

@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
TraceIdUtil.putIfAbsent();//生成trace id放入MDC中
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
TraceIdUtil.remove();//移除MDC中的trace id
}
}
}

Interceptor

@Configuration
public class LogInterceptor implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AsyncHandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
TraceIdUtil.putIfAbsent();//生成trace id放入MDC中
return AsyncHandlerInterceptor.super.preHandle(request, response, handler);
}

@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler, Exception ex) throws Exception {
TraceIdUtil.remove();//移除MDC中的trace id
AsyncHandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
});
WebMvcConfigurer.super.addInterceptors(registry);
}
}

2.1.2 業務中使用

正常使用logger,無需關心trace id。例如:

@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserController {

@Autowired
private UserService userService;

@GetMapping("/{userId}")
public UserDto queryUser(@PathVariable Long userId) {
log.info("query user by id:{}", userId);
UserDto user = userService.query(userId);
log.info("query user result:{}", user);
return user;
}
}

請求該接口將輸出如下的日志樣式:

2022-04-05 09:40:17.638 [http-nio-8080-exec-1] [a02b13d81c224e49956afd4efbb85ca8] INFO  com.nk.webapp.controller.UserController - ready to query user by id:1
2022-04-05 09:40:17.670 [http-nio-8080-exec-1] [a02b13d81c224e49956afd4efbb85ca8] INFO com.nk.webapp.controller.UserController - query result:UserDto(userId=1, username=zhang3, age=23, email=abc@example.com)

四、總結

日志鏈路的跟蹤核心是使用MDC作為trace id載體,在業務開始階段一般通過攔截器就生成trace id并放入到MDC中,并根據MDC的相關特性將trace id投射到日志文本中,從而實現在同一個業務調用鏈路中的日志具有唯一標識。

責任編輯:武曉燕 來源: GreatSQL社區
相關推薦

2023-01-04 08:21:02

Loki配置日志

2019-01-02 09:30:59

MySQL數據庫日志審計

2020-09-08 08:44:36

日志記錄基礎設施安全漏洞

2009-07-08 14:24:43

Java日志系統跟蹤調試

2012-05-10 13:42:26

Java網絡爬蟲

2013-08-02 14:19:50

Java日志緩存

2021-01-25 15:00:44

微服務分布式日志

2011-11-02 15:42:27

2010-05-14 14:21:18

2021-08-08 08:17:45

事件響應日志網絡安全

2020-05-26 11:59:30

日志鏈路微服務架構

2021-05-13 17:02:38

MDC腳手架日志

2024-09-09 17:06:32

2019-11-25 11:20:08

FlutterWeb應用軟件開發

2022-02-15 17:56:19

SpringBoot日志

2009-12-22 10:46:35

2011-03-21 16:10:08

SQL Server日志

2023-09-18 11:36:35

2009-07-29 17:44:02

ibmdwJava

2010-08-05 08:49:19

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久91 | 视频1区 | 六月色婷 | 成人午夜激情 | 一区二区亚洲 | 亚洲天堂中文字幕 | 女人天堂av| 欧美激情精品久久久久久免费 | 日韩精品一二三区 | 亚洲天堂男人的天堂 | 中文字幕欧美日韩 | 欧美一级片在线观看 | 日韩伦理一区二区 | 91在线第一页 | 一区二区三区免费 | 成人在线视频网 | 国产特一级黄色片 | 中文字幕一区在线观看视频 | 91久久精品一区二区二区 | 国产精品久久福利 | 成人黄页在线观看 | 精品国产乱码久久久久久88av | 黄色一级大片在线免费看产 | 午夜精品福利视频 | 国产精品视频网 | 香蕉久久网| 伊人一区 | 精品91久久久 | 国产亚洲精品美女久久久久久久久久 | 自拍偷拍亚洲视频 | 亚洲 精品 综合 精品 自拍 | 日韩国产欧美一区 | 波多野结衣一区二区三区在线观看 | 亚洲视频国产视频 | 日韩精品福利 | 日韩av看片| 1级毛片 | 中文字幕在线看第二 | 一区二区三区免费 | 欧美电影免费观看高清 | 精品久久久久久久久亚洲 |