zoukankan      html  css  js  c++  java
  • log4j MDC用户操作日志追踪配置

    一、MDC介绍

            MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。某些应用程序采用多线程的方式来处理多个用户的请求。在一个用户的使用过程中,可能有多个不同的线程来进行处理。典型的例子是 Web 应用服务器。当用户访问某个页面时,应用服务器可能会创建一个新的线程来处理该请求,也可能从线程池中复用已有的线程。在一个用户的会话存续期间,可能有多个线程处理过该用户的请求。这使得比较难以区分不同用户所对应的日志。当需要追踪某个用户在系统中的相关日志记录时,就会变得很麻烦。

      一种解决的办法是采用自定义的日志格式,把用户的信息采用某种方式编码在日志记录中。这种方式的问题在于要求在每个使用日志记录器的类中,都可以访问到用户相关的信息。这样才可能在记录日志时使用。这样的条件通常是比较难以满足的。MDC 的作用是解决这个问题。

      MDC 可以看成是一个与当前线程绑定的哈希表,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。

    二、MDC使用案例

         相对比较大的项目来说,一般会有多个开发人员,如果每个开发人员凭自己的理解打印日志,那么当用户反馈问题时,很难通过日志去快速的定位到出错原因,也会消耗更多的时间。所以针对这种问题,一般会定义好整个项目的日志格式,如果是需要追踪的日志,开发人员调用统一的打印方法,在日志配置文件里面定义好相应的字段,通过MDC功能就能很好的解决问题。

         比如我们可以事先把用户的sessionId,登录用户的用户名,访问的城市id,当前访问商户id等信息定义成字段,线程开始时把值放入MDC里面,后续在其他地方就能直接使用,无需再去设置了。

        使用MDC来记录日志,一来可以规范多开发下日志格式的一致性,二来可以为后续使用ELK对日志进行分析

    代码: filter

    public class RequestNoFilter implements Filter {

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain chain) throws IOException, ServletException {
    // 为每个请求设置唯一编号,用于打日志
    MDC.put("RequestNo", System.currentTimeMillis() + String.valueOf(Math.random()).substring(2, 8));
    chain.doFilter(srequest, sresponse);
    MDC.put("RequestNo", "");
    return;
    }

    public void destroy() {
    }
    }

    配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="/cpic/jtxlj/log" />
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- 日志输出编码 -->
    <Encoding>UTF-8</Encoding>
    <layout class="ch.qos.logback.classic.PatternLayout">
    <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
    <pattern>%X{RequestNo}-%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </layout>
    </appender>
    <!-- 按照每天生成日志文件 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <Encoding>UTF-8</Encoding>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
    <FileNamePattern>${LOG_HOME}/bluewhale.log.%d{yyyy-MM-dd}-No.%i.log</FileNamePattern>
    <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
    <maxFileSize>100MB</maxFileSize>
    </timeBasedFileNamingAndTriggeringPolicy>
    <MaxHistory>100</MaxHistory>
    </rollingPolicy>
    <encoder>
    <pattern>
    <![CDATA[%X{RequestNo}-%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%L] - %msg%n]]>
    </pattern>
    </encoder>
    </appender>

    <!-- 日志输出级别 -->
    <root level="INFO">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="FILE" />
    </root>
    <logger name="org.hibernate" level="INFO" />
    <logger name="com.huateng" level="DEBUG" />
    <logger name="org.springframework" level="ERROR" />
    </configuration>

  • 相关阅读:
    HDU 5793 A Boring Question 2016多校第六场1001
    HDU 5803 Zhu’s Math Problem 2016多校第六场1011 数位dp
    HDU 5787 K-wolf Number 2016多校第五场1007 数位dp
    HDU 5791 Two 2016多校第五场1011 LCS
    HDU 5773 The All-purpose Zero 2016多校第四场1010 LIS
    HDU 5768 Lucky7 2016多校第四场1005
    hdu 5002 Tree(LCT裸题)
    Wannafly挑战赛1 C MMSet2
    hdu 5398 GCD Tree(LCT动态维护最大生成树)
    hdu 5967 小R与手机(LCT裸题)
  • 原文地址:https://www.cnblogs.com/zxf330301/p/8459055.html
Copyright © 2011-2022 走看看