使用log4j|使用log4j MDC实现日志追踪
目录
- log4j MDC实现日志追踪
- 1、新建线程处理类 ThreadContext
- 2、添加工具类TraceUtil
- 3、添加ContextFilter
- 4、在webConfiguriation注册filter
- 5、修改log4j日志配置文件,设置日志traceId
- log4j2实现日志跟踪
- 日志跟踪
- 我们可以通过过滤器实现以上的功能
log4j MDC实现日志追踪 MDC 中包含的可以被同一线程中执行的代码所访问内容。当前线程的子线程会继承其父线程中的 MDC 的内容。记录日志时,只需要从 MDC 中获取所需的信息即可。
作用:
使用MDC来记录日志,可以规范多开发下日志格式。
1、新建线程处理类 ThreadContext
import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Optional; /** * 线程上下文 * * @date 2017年3月1日 * @since 1.0.0 */public class ThreadContext {/*** 线程上下文变量的持有者*/private final static ThreadLocal
2、添加工具类TraceUtil
import java.util.UUID; import org.slf4j.MDC; import ThreadContext; /** * trace工具 * * @date 2017年3月10日 * @since 1.0.0 */public class TraceUtil {public static void traceStart() {ThreadContext.init(); String traceId = generateTraceId(); MDC.put('traceId', traceId); ThreadContext.putTraceId(traceId); }public static void traceEnd() {MDC.clear(); ThreadContext.clean(); }/*** 生成跟踪ID** @return*/private static String generateTraceId() {return UUID.randomUUID().toString(); }}
3、添加ContextFilter
对于每个请求随机生成RequestID并放入MDC
import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.web.filter.OncePerRequestFilter; import com.pingan.manpan.common.util.TraceUtil; import com.pingan.manpan.user.dto.ThreadContext; import com.pingan.manpan.web.common.surpport.IpUtils; /** * 上下文Filter * * @date 2017/3/10 * @since 1.0.0 *///@Order 标记组件的加载顺序@Order(Ordered.HIGHEST_PRECEDENCE)public class ContextFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {try {ThreadContext.putClientIp(IpUtils.getClientIp(request)); TraceUtil.traceStart(); filterChain.doFilter(request, response); } finally {TraceUtil.traceEnd(); }}}
4、在webConfiguriation注册filter
/*** 请求上下文,应该在最外层** @return*/@Beanpublic FilterRegistrationBean requestContextRepositoryFilterRegistrationBean() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new ContextFilter()); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; }
5、修改log4j日志配置文件,设置日志traceId
${FILE_LOG_PATTERN} ${LOG_FILE}${LOG_FILE_SUFFIX} 127.0.0.1 ${LOG_FILE}.%d{yyyy-MM-dd}${LOG_FILE_SUFFIX} local6 514${FILE_LOG_PATTERN}
log4j2实现日志跟踪
日志跟踪
在每条日志前添加一个随机字符串并且确保同一个请求的字符串相同。如下:c6019df137174d2b98631474db4156b7为此次请求的标识。通过次标识可以查询到所有该请求的日志信息
[traceID:c6019df137174d2b98631474db4156b7]-[2020-08-11 19:56:58:204]-[http-nio-8803-exec-4]-同时可以将此标识返回给前端,便于问题查询。traceID: c6019df137174d2b98631474db4156b7
[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]-
Access-Control-Allow-Credentials: trueAccess-Control-Allow-Origin: http://test.page.qingin.cnCache-Control: max-age=30Connection: keep-aliveContent-Type: application/json; charset=UTF-8Date: Tue, 11 Aug 2020 12:02:19 GMTExpires: Tue, 11 Aug 2020 12:02:49 GMTServer: nginx/1.16.1traceID: c6019df137174d2b98631474db4156b7Transfer-Encoding: chunkedVary: OriginVary: Access-Control-Request-MethodVary: 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 = "https://www.it610.com/article/这是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); @Overridepublic void init(FilterConfig filterConfig) throws ServletException {description = filterConfig.getInitParameter("DESCRIPTION"); System.out.println("过滤器初始化:"+ description); }@Overridepublic 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.xmlThreadContext.put(TRACE_ID, traceId); // 随机数放到Header中,在Response Headers中可查看到此数据resp.addHeader(TRACE_ID, traceId); filterChain.doFilter(req, resp); ThreadContext.clearAll(); }@Overridepublic void destroy() {System.out.println("过滤器,被销毁:"+ description); }}
log4j2.xml
logs
【使用log4j|使用log4j MDC实现日志追踪】以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
推荐阅读
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- iOS中的Block
- Linux下面如何查看tomcat已经使用多少线程
- 使用composer自动加载类文件
- android|android studio中ndk的使用
- 使用协程爬取网页,计算网页数据大小