系统日志增加mdc全局id等信息,方便快速定位问题
程序员文章站
2022-05-29 18:55:36
...
系统需要优化,在日志中加入MDC全局id等信息,便于根据id快速定位问题
1.先注册个拦截器
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*注册 实现日志拦截器
*
* @Author YS.MAO
* @date 2020/11/19 14:22
* @Version 1.0
*/
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {
@Autowired
private LogInterceptor logInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(logInterceptor);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
2.定义个拦截器
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
/**
* 日志自定义拦截类,将日志操作加入全局mdc
*
* @Author YS.MAO
* @date 2020/11/19 14:16
* @Version 1.0
*/
@Component
public class LogInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(LogInterceptor.class);
/**
* 设备
*/
private static final String USER_AGENT = "user-agent";
/**
* 位置定义
*/
private static final String UNKNOWN = "unknown";
/**
* 本地ip
*/
private static final String LOCAL_IP = "0:0:0:0:0:0:0:1";
/**
* 全局mdc
*/
private static final String TRACE_ID = "traceId";
/**
* 全局ip
*/
private static final String IP = "ip";
/**
* 全局url
*/
private static final String URL = "url";
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object object) throws Exception {
// 定义一个全局的tranceId 使用32为uuid+随机6位数字
String traceId =
UUID.randomUUID().toString().replaceAll("-", "") + "-" + ((int)((Math.random() * 9 + 1) * 100000));
// 放入日志全局id
MDC.put(TRACE_ID, traceId);
// 放入ip
MDC.put(IP, getIpAddr(httpServletRequest));
// LOGGER.info("put traceId ({}) to logger", traceId);
// 获取url地址
String url = httpServletRequest.getRequestURI();
// 放入设备
MDC.put(URL,url);
// 日志打印 地址--设备--访问接口和访问ip
// LOGGER.info(url);
// LOGGER.info("UserAgent: {}", httpServletRequest.getHeader(USER_AGENT));
LOGGER.info("get request interface: {}, get ip address: {}, UserAgent: {}", url, getIpAddr(httpServletRequest),httpServletRequest.getHeader(USER_AGENT));
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object object, ModelAndView modelAndView) throws Exception {
//执行成功,获取日志全局id
// String traceId = MDC.get(TRACE_ID);
// LOGGER.info("remove traceId ({}) from logger", traceId);
//删除当前操作全局id
MDC.remove(TRACE_ID);
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Object object, Exception e) throws Exception {
// 自定义
}
/**
* 根据request请求获取ip
*
* @param request
* 请求
* @return ip 获取的ip
*/
private String getIpAddr(HttpServletRequest request) {
// 获取请求头信息
String ip = request.getHeader("x-forwarded-for");
// LOGGER.info("get all ip:" + ip);
// 取不到值 执行不同请求头信息
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
// 如果本地调用 默认返回 127.0.0.1
if (LOCAL_IP.equals(ip)) {
ip = "127.0.0.1";
}
// 如果是多级代理,取第一个ip为客户真实ip
if (ip != null && ip.split(",").length > 1) {
ip = ip.split(",")[0];
}
return ip;
}
}
拦截器这里可以在定义util类将里面的方法抽出来
3.日志文件增加配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<contextName>logback</contextName>
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<property name="LOG_HOME" value="/opt/logs/bank-common/sys-common" />
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%X{traceId}表示mdc全局id,%ip 表示ip , %thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%X{ip}] [%X{url}] [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/console.log.%d{yyyy-MM-dd}.%i.log
</FileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<!--<!–过滤 INFO–>-->
<!--<level>INFO</level>-->
<!--<!–匹配到就禁止–>-->
<!--<onMatch>ACCEPT</onMatch>-->
<!--<!–没有匹配到就允许–>-->
<!--<onMismatch>DENY</onMismatch>-->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%X{traceId}表示mdc全局id,%ip 表示ip , %thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%X{ip}] [%X{url}] [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志输出级别 -->
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE" />
</root>
</configuration>
上一篇: 取消npm代理或淘宝镜像
下一篇: Python实现的爬虫刷回复功能示例