【问题标题】:Spring Boot & Slf4j 2 Http request metadata logging interceptor?Spring Boot 和 Slf4j 2 Http 请求元数据日志记录拦截器?
【发布时间】:2018-06-06 16:25:53
【问题描述】:

我想配置我的日志记录设置,以便传入请求带有一个 id(即 UUID)标记,用于跟踪整个应用程序(即控制器类、服务类等)以及其他相关的请求和进程请求中的信息(即主机名、IP 地址...)。

参考 slf4j 2 文档,我看到提到了ThreadContext。对于向我的 spring-boot 应用程序发出的每个请求,我都想做类似的事情:

ThreadContext.put("id", UUID.randomUUID().toString());
ThreadContext.put("ipAddress", this.request.getRemoteAddr());
...

并在我的调试器的 PatternLayout 中调用这些键,如下所示:%X{key}。理想情况下,这将产生类似于以下内容:

[INFO] request #UUID1 #IP1: start.
[INFO] request #UUID1 #IP1: do something controller class 
[INFO] request #UUID2 #IP2: start.
[INFO] request #UUID1 #IP1: do something service class
[INFO] request #UUID2 #IP2: do something controller class 
[INFO] request #UUID2 #IP2: do something service class 
[INFO] request #UUID1 #IP1: end.
[INFO] request #UUID2 #IP2: end.

虽然我不确定如何开始实际实施这一点。任何见解将不胜感激!

【问题讨论】:

    标签: java spring spring-boot log4j log4j2


    【解决方案1】:

    您应该使用 slf4j 查看 MDC(映射诊断上下文) https://ivanursul.com/slf4j-mdc

    创建一个 Servlet 过滤器,在 MDC 中设置所需的参数,它们将在整个请求中可用并自动记录。

    【讨论】:

    • 太棒了,这与我尝试的方法相似。我会仔细看看的。谢谢!
    【解决方案2】:

    Spring Cloud Sleuth 将为您完成所有这些工作。只需将其包含在您的类路径中,并将您关心的属性添加到您的日志输出中。它还自动检测控制器和客户端以传递标头属性。

    【讨论】:

    • 实际上,Spring Cloud Sleuth 不会为你做这一切。请注意,接受的答案是向 RequestContext 添加更多属性,而不仅仅是跟踪和跨度 ID。 OTOH,Log4j-Audit 将提供执行示例中显示的所有操作的能力,同时还提供对审计日志记录的支持。
    【解决方案3】:

    使用实现 Filter 类的类,我能够通过使用以下代码以及调用 Log4j 2 PatternLayout 中的键来获得所需的行为:

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.logging.log4j.ThreadContext;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.RequestBody;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.FilterChain;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.TimeZone;
    import java.util.UUID;
    
    @Component
    public class RequestResponseLoggingFilter implements Filter {
        private FilterConfig filterConfig;
        private static String TZ_NAME = "timezoneOffset";
    
        private static final Logger LOGGER = LogManager.getLogger(RequestBody.class);
    
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }
    
    /**
     * Sample filter that populates the MDC on every request.
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
    
        String requestId = request.getHeader("requestId");
    
        if (requestId == null) {
            requestId = UUID.randomUUID().toString();
        }
    
        ThreadContext.put("requestId", requestId);
        ThreadContext.put("ipAddress", request.getRemoteAddr());
        HttpSession session = request.getSession(false);
        TimeZone timeZone = null;
        ThreadContext.put("hostname", servletRequest.getServerName());
        ThreadContext.put("locale", servletRequest.getLocale().getDisplayName());
        if (timeZone == null) {
            timeZone = TimeZone.getDefault();
        }
        ThreadContext.put("timezone", timeZone.getDisplayName());
        LOGGER.info(
                "Logging Request {} : {}", request.getMethod(),
                request.getRequestURI());
        filterChain.doFilter(servletRequest, servletResponse);
        LOGGER.info(
                "Logging Response {} : {}",
                response.getStatus(), response.getContentType());
        ThreadContext.clearMap();
    }
    
    @Override
    public void destroy() {
    }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-06-13
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 2018-01-05
      • 2023-02-09
      • 1970-01-01
      • 2019-11-17
      • 1970-01-01
      相关资源
      最近更新 更多