zoukankan      html  css  js  c++  java
  • SpringBoot正确打日志的姿势

    前篇

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

    本文简介

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

    HTTP 请求日志

    imgimg

    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:{}, 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("
    ", "");
            }
        }
    
    }
    
    

    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}
    

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

    img

    Spring Boot 定制 parent 快速构建应用

    Spring Boot 容器化部署 - Docker

    SpringBot中教你手把手配置 https

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

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

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

    Spring Boot 异常处理

    Spring Boot 配置 - 配置信息加密

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

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

    img

    本文由博客一文多发平台 OpenWrite 发布!

  • 相关阅读:
    Linux 安装多版本Python
    ElasticSearch 镜像 & 安装 & 简易集群
    SpringBoot-异步调用@Async
    SprinigBoot整合Kafka
    Kafka快速安装部署
    Linux-JDK安装
    npm / yarn 配置镜像、使用方法
    React搭建项目(全家桶)
    原生JS 将canvas生成图片
    原生 JS 的 Base64 转码
  • 原文地址:https://www.cnblogs.com/springforall/p/11826833.html
Copyright © 2011-2022 走看看