先看下MDC是什麼
Mapped Diagnostic Context,用於打LOG時跟蹤一個「會話「、一個」事務「。舉例,有一個web controller,在同一時間可能收到來自多個客戶端的請求,若是一個請求發生了錯誤,咱們要跟蹤這個請求從controller開始一步步都執行到了哪些代碼、有哪些log的輸出。這時咱們能夠看log文件,可是log文件是多個請求同時記錄的,基本沒法分辨哪行是哪一個請求產生的,雖然咱們能夠看線程,但線程可能被複用,也是很難分辨出,這時MDC就派上用場了。html
咱們能夠加一個web filter,在請求進來時,把」標識「放到MDC context中,好比:put( ip, 8.8.8.8), put(username, 'yang'),在filter結束時把context再清掉,便可在整個請求處理過程當中,均可以打印出ip, username這些數據,就能夠方便的用於日誌跟蹤。java
在SpringBoot中怎麼用
1. 寫一個LogInterceptor,用於統一處理MDC:
-
-
public class LogInterceptor implements HandlerInterceptor {
-
-
private final static String REQUEST_ID = "requestId";
-
private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);
-
-
-
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
-
String xForwardedForHeader = httpServletRequest.getHeader(
"X-Forwarded-For");
-
String remoteIp = httpServletRequest.getRemoteAddr();
-
String uuid = UUID.randomUUID().toString();
-
LOGGER.info(
"put requestId ({}) to logger", uuid);
-
LOGGER.info(
"request id:{}, client ip:{}, X-Forwarded-For:{}", uuid, remoteIp, xForwardedForHeader);
-
MDC.put(REQUEST_ID, uuid);
-
-
-
-
-
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
-
String uuid = MDC.get(REQUEST_ID);
-
LOGGER.info(
"remove requestId ({}) from logger", uuid);
-
-
-
-
-
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
-
-
-
關鍵代碼在於:MDC.put(REQUEST_ID, uuid);
2. 註冊一下這個Interceptor,寫一個WebMvcConfigurer類:
-
-
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
-
-
private LogInterceptor logInterceptor;
-
-
-
public void addInterceptors(InterceptorRegistry registry) {
-
registry.addInterceptor(logInterceptor);
-
super.addInterceptors(registry);
-
-
3. 放一個logback.xml到src/main/resources/目錄中,用於配置logback的參數,如沒有,請新建一個
-
<configuration scan="true" scanPeriod="30 seconds" debug="true">
-
-
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-
<target>System.out</target>
-
-
<pattern>[%date{ISO8601}] [%-5level] - [%thread] [%X{requestId}] [%logger] [%X{akkaSource}] - %msg %rootException %n
-
-
-
-
-
-
-
-
-
<appender-ref ref="STDOUT"/>
-
-
-
注意這個<pattern/>中配置了輸出 requestId
4. 最後看下效果,下面加粗的即爲requestId
[2017-12-14 16:08:45,677] [INFO ] - [http-nio-8080-exec-1] [a08f86cd-6743-48ce-816a-f5ee61b802b8]