使⽤log4jMDC实现⽇志追踪
⽬录
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<Map<String, Object>> CTX_HOLDER = new ThreadLocal<Map<String, Object>>();
static {
CTX_HOLDER.set(new HashMap<String, Object>());
}
/**
* traceID
*/
private final static String TRACE_ID_KEY = "traceId";
/**
* 会话ID
*/
private final static String SESSION_KEY = "token";
/**
* 操作⽤户ID
*/
private final static String VISITOR_ID_KEY = "userId";
/**
* 操作⽤户名
*/
private final static String VISITOR_NAME_KEY = "userName";
/**
* 客户端IP
*/
private static final String CLIENT_IP_KEY = "clientIp";
/**
* 添加内容到线程上下⽂中
*
* @param key
* @param value
*/
public final static void putContext(String key, Object value) {
Map<String, Object> ctx = ();
if (ctx == null) {
return;
}
ctx.put(key, value);
}
/**
* 从线程上下⽂中获取内容
*
* @param key
*/
@SuppressWarnings("unchecked")
public final static <T extends Object> T getContext(String key) {        Map<String, Object> ctx = ();
if (ctx == null) {
return null;
log4j2不打印日志}
return (T) (key);
}
/**
* 获取线程上下⽂
*/
public final static Map<String, Object> getContext() {
Map<String, Object> ctx = ();
if (ctx == null) {
return null;
}
return ctx;
}
/**
* 删除上下⽂中的key
*
* @param key
*/
public final static void remove(String key) {
Map<String, Object> ctx = ();
if (ctx != null) {
}
}
/**
* 上下⽂中是否包含此key
*
* @param key
* @return
*/
public final static boolean contains(String key) {
Map<String, Object> ctx = ();
if (ctx != null) {
ainsKey(key);
}
return false;
}
/**
* 清空线程上下⽂
*/
public final static void clean() {
ve();
}
/**
* 初始化线程上下⽂
*/
public final static void init() {
CTX_HOLDER.set(new HashMap<String, Object>());
}
/**
* 设置traceID数据
*/
public final static void putTraceId(String traceId) {
putContext(TRACE_ID_KEY, traceId);
}
/**
* 获取traceID数据
*/
public final static String getTraceId() {
return getContext(TRACE_ID_KEY);
}
/**
* 设置会话的⽤户ID
*/
public final static void putUserId(Integer userId) {
putContext(VISITOR_ID_KEY, userId);
}
/
**
* 设置会话的⽤户ID
*/
public final static int getUserId() {
Integer val = getContext(VISITOR_ID_KEY);
return val == null ? 0 : val;
}
/**
* 设置会话的⽤户名
*/
public final static void putUserName(String userName) {
putContext(VISITOR_NAME_KEY, userName);
}
/**
* 获取会话的⽤户名称
*/
public final static String getUserName() {
return Optional.ofNullable(getContext(VISITOR_NAME_KEY))                .map(name -> String.valueOf(name))
.orElse("");
}
/**
* 取出IP
*
* @return
*/
public static final String getClientIp() {
return getContext(CLIENT_IP_KEY);
}
/**
* 设置IP
*
* @param ip
*/
public static final void putClientIp(String ip) {
putContext(CLIENT_IP_KEY, ip);
}
/**
* 设置会话ID
*
* @param token
*/
public static void putSessionId(String token) {
putContext(SESSION_KEY, token);
}
/
**
* 获取会话ID
*
* @param token
*/
public static String getSessionId(String token) {
return getContext(SESSION_KEY);
}
/**
* 清空会话数据
*/
public final static void removeSessionId() {
remove(SESSION_KEY);
}
}
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 Ordered;
import annotation.Order;
import org.springframework.web.filter.OncePerRequestFilter;
import com.pingan.manpanmon.util.TraceUtil;
import com.pingan.manpan.user.dto.ThreadContext;
import com.pingan.manpan.webmon.surpport.IpUtils;
/**
* 上下⽂Filter
*
* @date 2017/3/10
* @since 1.0.0
*/
//@Order 标记组件的加载顺序
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ContextFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,                                    FilterChain filterChain) throws ServletException, IOException {
try {
ThreadContext.ClientIp(request));
filterChain.doFilter(request, response);
} finally {
}
}
}
4、在webConfiguriation注册filter
/**
* 请求上下⽂,应该在最外层
*
* @return
*/
@Bean
public FilterRegistrationBean requestContextRepositoryFilterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new ContextFilter());
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
5、修改log4j⽇志配置⽂件,设置⽇志traceId
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<jmxConfigurator/>
<property name="LOG_LEVEL_PATTERN" value="%X{traceId:-} %5p"/>
<property name="LOG_FILE" value="${LOG_PATH}/web.logx"/>
<property name="LOG_FILE_SUFFIX" value=".logx"/>
<include resource="org/springframework/boot/logging/l"/>
<include resource="org/springframework/boot/logging/l"/>
<appender name="FILE"
class="ch.olling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
<file>${LOG_FILE}${LOG_FILE_SUFFIX}</file>
<rollingPolicy class="ch.olling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}${LOG_FILE_SUFFIX}</fileNamePattern>
</rollingPolicy>
</appender>
<appender name="SYSLOG" class="ch.qos.logback.classic.SyslogAppender">
<syslogHost>127.0.0.1</syslogHost>
<facility>local6</facility>
<port>514</port>
<suffixPattern>${FILE_LOG_PATTERN}</suffixPattern>
</appender>
<logger name="druid.sql" level="DEBUG" />
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="SYSLOG"/>
</root>
</configuration>
log4j2实现⽇志跟踪
⽇志跟踪
在每条⽇志前添加⼀个随机字符串并且确保同⼀个请求的字符串相同。如下: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: test.page.qingin
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
我们可以通过过滤器实现以上的功能

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。