当前位置: 首页 > 工具软件 > cache4j > 使用案例 >

log4j2实现日志跟踪

钱星辰
2023-12-01

日志跟踪

  • 在每条日志前添加一个随机字符串并且确保同一个请求的字符串相同。如下:c6019df137174d2b98631474db4156b7为此次请求的标识。通过次标识可以查询到所有该请求的日志信息
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:204]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:204]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:205]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:205]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:209]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:214]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:223]-[http-nio-8803-exec-4]-
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:224]-[http-nio-8803-exec-4]-
  • 同时可以将此标识返回给前端,便于问题查询。traceID: c6019df137174d2b98631474db4156b7
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://test.page.qingin.cn
Cache-Control: max-age=30
Connection: keep-alive
Content-Type: application/json;charset=UTF-8
Date: Tue, 11 Aug 2020 12:02:19 GMT
Expires: Tue, 11 Aug 2020 12:02:49 GMT
Server: nginx/1.16.1
traceID: c6019df137174d2b98631474db4156b7
Transfer-Encoding: chunked
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers

我们可以通过过滤器实现以上的功能

  • Log4j2Filter.java
package com.generator.admin.filter;

import org.apache.logging.log4j.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * @calssName Log4j2Filter
 * @Description 对用户的请求添加日志编号,并将此编号返回给前端,便于日志查询
 */
@WebFilter(filterName = "Log4j2Filter", urlPatterns = "/*", initParams = {@WebInitParam(name = "DESCRIPTION", value = "这是Log4j2Filter过滤器")})
public class Log4j2Filter implements Filter {

    private String description;
    public static final String TRACE_ID = "traceID";
    private static final Logger logger = LoggerFactory.getLogger(Log4j2Filter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        description = filterConfig.getInitParameter("DESCRIPTION");
        System.out.println("过滤器初始化:"+ description);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException,ServletException {
            
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse resp = (HttpServletResponse) servletResponse;
        
        // 生成一个随机数给到前端
        String traceId = UUID.randomUUID().toString().replace("-", "");
        // 随机数放到此线程的上下文中,可以在每条日志前加入。具体看下面log4j2.xml
        ThreadContext.put(TRACE_ID, traceId);
        // 随机数放到Header中,在Response Headers中可查看到此数据
        resp.addHeader(TRACE_ID, traceId);  
        filterChain.doFilter(req, resp);
        ThreadContext.clearAll();
    }

    @Override
    public void destroy() {
        System.out.println("过滤器,被销毁:"+ description);
    }
}
  • log4j2.xml <PatternLayout pattern="[traceID:%X{traceID}]-[%d{yyyy-MM-dd HH:mm:ss:SSS}]-[%t]-[%p]-[%l]-%m%n"/>
<?xml version="1.0" encoding="UTF-8"?>

<!--设置log4j2的自身log级别为warn-->
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="warn" monitorInterval="30">
    
    <!--全局参数-->
    <Properties>
        <Property name="logPath">logs</Property>
    </Properties>
    
    <!--先定义所有的appender-->
    <appenders>
        <!--这个输出控制台的配置-->
        <console name="Console" target="SYSTEM_OUT">
            <!-- traceID:就是在过滤器中生成的随机数 -->
            <PatternLayout pattern="[traceID:%X{traceID}]-[%d{yyyy-MM-dd HH:mm:ss:SSS}]-[%t]-[%p]-[%l]-%m%n"/>
        </console>
    </appenders>

    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的debug信息-->
        <logger name="org.springframework" level="INFO"></logger>
        <logger name="org.mybatis" level="INFO"></logger>
        <logger name="com.zaxxer" level="WARN"></logger>
        <!-- com.generator开发/测试环境用DEBUG,并用控制台输出即可 -->
        <logger name="com.generator" level="DEBUG" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <!-- 未指定的包都按此 level 打印日志 -->
        <root level="DEBUG">
            <appender-ref ref="Console"/>
        </root>
    </loggers>

</configuration>

最后

  • 如果在这里获得过启发和思考,希望点赞支持!对于内容有不同的看法欢迎来信交流。
  • 技术栈 >> java
  • 邮箱 >> 15673219519@163.com

相关博客

springboot 默认日志框架logback日志跟踪以及子线程的处理情况

 类似资料: