前篇
Spring Boot Log4j2 日志性能之巅
本文简介
前篇侧重 Log4j2 的配置, 本篇侧重统一日志处理的应用, 以下包含 HTTP 请求的日志处理 Exception 异常日志处理
HTTP 请求日志
1 明确日志记录的内容
示例: 用户 IP 地址 MethodURI 请求参数请求体
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:{}, Method:{}, URI:{}", request.getRemoteAddr(), request.getMethod(), 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, 0, 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"
说明:
- MDC.put("user", request.getRemoteUser());
- => %X{user}
Exception 异常日志
1 全局异常处理
- ExceptionController.java
- package com.anoyi.controller;
- import com.anoyi.bean.ResponseBean;
- import lombok.AllArgsConstructor;
- import lombok.extern.log4j.Log4j2;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.ResponseBody;
- @ControllerAdvice
- @Log4j2
- @AllArgsConstructor
- public class ExceptionController {
- /**
- * 抛出错误前, 打印错误日志
- * **/
- @ExceptionHandler(Exception.class)
- @ResponseBody
- public ResponseBean handleException(Exception exception){
- log.error(exception.getMessage(), exception);
- return ResponseBean.error(exception);
- }
- }
来源: http://www.jianshu.com/p/c883b86c34fa