查看原文
其他

SpringBoot正确打日志的姿势

SpringForAll社区 SpringForAll社区 2021-05-26
点击上方☝SpringForAll社区 轻松关注!
及时获取有趣有料的技术文章

img

前篇

Spring Boot 日志处理你还在用Logback?

本文简介

前篇侧重 Log4j2 的配置,本篇侧重统一日志处理的应用,以下包含 HTTP 请求的日志处理、Exception 异常日志处理。

HTTP 请求日志

img

1、明确日志记录的内容

示例:用户、IP地址、Method、URI、请求参数、请求体

2、全局拦截 MDCFilter.java

1package com.anoyi.config.server;
2
3import lombok.extern.log4j.Log4j2;
4import org.slf4j.MDC;
5import org.springframework.http.HttpMethod;
6import org.springframework.stereotype.Component;
7import org.springframework.web.filter.OncePerRequestFilter;
8
9import javax.servlet.FilterChain;
10import javax.servlet.ReadListener;
11import javax.servlet.ServletException;
12import javax.servlet.ServletInputStream;
13import javax.servlet.http.HttpServletRequest;
14import javax.servlet.http.HttpServletRequestWrapper;
15import javax.servlet.http.HttpServletResponse;
16import java.io.*;
17
18/**
19 * 拦截请求信息,添加到日志
20 */

21@Component
22@Log4j2
23public class MDCFilter extends OncePerRequestFilter {
24
25    @Override
26    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
27        try {
28            MDC.put("user", request.getRemoteUser());
29            String query = request.getQueryString() != null ? "?" + request.getQueryString() : "";
30            if (request.getMethod().equals(HttpMethod.POST.name())) {
31                MultiReadHttpServletRequest multiReadHttpServletRequest = new MultiReadHttpServletRequest(request);
32                log.info("IP:{}, Method:{}, URI:{} Body:{}", request.getRemoteAddr(), request.getMethod(), request.getRequestURI() + query, multiReadHttpServletRequest.getRequestBody());
33                chain.doFilter(multiReadHttpServletRequest, response);
34            } else {
35                log.info("IP:{}, Method:{}, URI:{}", request.getRemoteAddr(), request.getMethod(), request.getRequestURI() + query);
36                chain.doFilter(request, response);
37            }
38        } finally {
39            MDC.clear();
40        }
41    }
42
43    /**
44     * HttpServletRequest 请求体多读
45     */

46    class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
47
48        // 缓存 RequestBody
49        private String requestBody;
50
51        MultiReadHttpServletRequest(HttpServletRequest request) {
52            super(request);
53            requestBody = "";
54            try {
55                StringBuilder stringBuilder = new StringBuilder();
56                InputStream inputStream = request.getInputStream();
57                byte[] bs = new byte[1024];
58                int len;
59                while ((len = inputStream.read(bs)) != -1) {
60                    stringBuilder.append(new String(bs, 0, len));
61                }
62                requestBody = stringBuilder.toString();
63            } catch (IOException e) {
64                e.printStackTrace();
65            }
66        }
67
68        @Override
69        public ServletInputStream getInputStream() throws IOException {
70            final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes());
71
72            return new ServletInputStream() {
73                public int read() throws IOException {
74                    return byteArrayInputStream.read();
75                }
76
77                @Override
78                public boolean isFinished() {
79                    return byteArrayInputStream.available() == 0;
80                }
81
82                @Override
83                public boolean isReady() {
84                    return true;
85                }
86
87                @Override
88                public void setReadListener(ReadListener readListener) {
89
90                }
91            };
92        }
93
94        @Override
95        public BufferedReader getReader() throws IOException {
96            return new BufferedReader(new InputStreamReader(this.getInputStream()));
97        }
98
99        String getRequestBody() {
100            return requestBody.replaceAll("\n""");
101        }
102    }
103
104}

3、配置日志 Pattern

1logging:
2  pattern:
3    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}

© 著作权归作者所有,转载或内容合作请联系作者


● Spring Boot 定制 parent 快速构建应用

● Spring Boot 容器化部署 - Docker

● SpringBot中教你手把手配置 https

● Spring Boot 日志处理你还在用Logback?

● 【双11狂欢的背后】微服务注册中心如何承载大型系统的千万级访问?

● Spring Boot 新一代监控你该这么玩

● Spring Boot 异常处理

● Spring Boot 配置 - 配置信息加密

● 拒绝黑盒应用-Spring Boot 应用可视化监控

● 并发Bug之源有三,请睁大眼睛看清它们


如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存