SpringBoot正確打日誌的姿勢
阿新 • • 發佈:2019-12-31
前篇
本文簡介
前篇側重 Log4j2 的配置,本篇側重統一日誌處理的應用,以下包含 HTTP 請求的日誌處理、Exception 異常日誌處理。
HTTP 請求日誌
img
1、明確日誌記錄的內容
示例:使用者、IP地址、Method、URI、請求引數、請求體
2、全域性攔截 MDCFilter.java
package com.anoyi.config.server;
import lombok.extern.log4j.Log4j2;
import org.slf4j.MDC;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
/**
* 攔截請求資訊,新增到日誌
*/
@Component
@Log4j2
public class MDCFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws ServletException,IOException {
try {
MDC.put("user",request.getRemoteUser());
String query = request.getQueryString() != null ? "?" + request.getQueryString() : "";
if (request.getMethod().equals(HttpMethod.POST.name())) {
MultiReadHttpServletRequest multiReadHttpServletRequest = new MultiReadHttpServletRequest(request);
log.info("IP:{},Method:{},URI:{} Body:{}",request.getRemoteAddr(),request.getMethod(),request.getRequestURI() + query,multiReadHttpServletRequest.getRequestBody());
chain.doFilter(multiReadHttpServletRequest,response);
} else {
log.info("IP:{},URI:{}",request.getRequestURI() + query);
chain.doFilter(request,response);
}
} finally {
MDC.clear();
}
}
/**
* HttpServletRequest 請求體多讀
*/
class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
// 快取 RequestBody
private String requestBody;
MultiReadHttpServletRequest(HttpServletRequest request) {
super(request);
requestBody = "";
try {
StringBuilder stringBuilder = new StringBuilder();
InputStream inputStream = request.getInputStream();
byte[] bs = new byte[1024];
int len;
while ((len = inputStream.read(bs)) != -1) {
stringBuilder.append(new String(bs,len));
}
requestBody = stringBuilder.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes());
return new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
String getRequestBody() {
return requestBody.replaceAll("\n","");
}
}
}
複製程式碼
3、配置日誌 Pattern
logging:
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%15.15t] %-40.40c{1.} [%X{user}] : %m%n%xwEx"複製程式碼
txt
說明: MDC.put("user",request.getRemoteUser()); => %X{user}
© 著作權歸作者所有,轉載或內容合作請聯絡作者
● Spring Boot 定製 parent 快速構建應用
● Spring Boot 日誌處理你還在用Logback?
● 【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?
本文由部落格一文多發平臺 OpenWrite 釋出!