文章目录 一、明确实现目标 二、搭建日志数据模型MTrackLog 三、自定义拦截器记录请求详情 四、注册拦截器让其生效 五、配置logback-spring.xml日志文件 六、看看示例输……
文
章
目
录
- 一、明确实现目标
- 二、搭建日志数据模型MTrackLog
- 三、自定义拦截器记录请求详情
- 四、注册拦截器让其生效
- 五、配置logback-spring.xml日志文件
- 六、看看示例输出日志长啥样
- 七、总结一下
企业系统开发记录API调用的详细信息是件非常重要的活,当排查系统问题、优化性能,还是进行审计追踪,这些日志能派上大用场。今天这篇文章,就来教大家怎么用Spring Boot实现API请求的自定义日志记录,还会涉及性能分析和日志分类!
一、明确实现目标
我们要达成的效果具体有这些:
- 每次HTTP请求都得记录日志,一个都不能漏。
- 日志里要包含URL、请求方法、请求参数、请求IP以及请求耗时这些关键信息。
- 根据请求耗时对日志进行分类,分为“FAST”(快速)、“NORMAL”(正常)、“SERIOUS”(严重,耗时较长)三类。
- 把这些日志单独写入一个叫
track.log
的专属日志文件里,这样就不会和主业务日志混在一起,方便查看和管理。 - 支持以JSON格式输出日志,这样用ELK、SLS这些工具做数据分析的时候就更方便了。
二、搭建日志数据模型MTrackLog
第一步,我们得定义一个日志数据模型,用来存放要记录的信息。这里创建一个MTrackLog
类,代码如下:
import lombok.Data;
import java.io.Serializable;
@Data
public class MTrackLog implements Serializable {
private String url;
private String method;
private long start;
private long end;
private String remoteIp;
private String parameter;
@Override
public String toString() {
long cost = end - start;
String level = cost >= 1500 ? \"SERIOUS\" : (cost > 300 ? \"NORMAL\" : \"FAST\");
return String.format(
\"{\"url\":\"%s\", \"method\":\"%s\", \"cost\":%d, \"level\":\"%s\", \"ip\":\"%s\", \"param\":\"%s\"}\",
url, method, cost, level, remoteIp, parameter
);
}
}
这个类里定义了URL、请求方法、请求开始和结束时间、请求IP、请求参数这些属性。toString
方法是用来把这些信息按照我们想要的格式输出,根据请求耗时划分等级,最后拼成一个JSON格式的字符串。大家要是有其他需求,还能往里面加traceId
、userId
这些字段。
三、自定义拦截器记录请求详情
接下来,我们写一个自定义拦截器,用来记录每次请求的详细信息。代码如下:
@Component
public class RequestTrackInterceptor implements HandlerInterceptor {
private static final Logger trackLogger = LoggerFactory.getLogger(\"TRACK_FILE_NAME\");
private static final String TRACK_LOG_KEY = \"_trackLog\";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
MTrackLog mTrackLog = new MTrackLog();
mTrackLog.setStart(System.currentTimeMillis());
request.setAttribute(TRACK_LOG_KEY, mTrackLog);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
Object obj = request.getAttribute(TRACK_LOG_KEY);
if (obj instanceof MTrackLog mTrackLog) {
mTrackLog.setEnd(System.currentTimeMillis());
mTrackLog.setMethod(request.getMethod());
mTrackLog.setUrl(request.getRequestURL().toString());
mTrackLog.setRemoteIp(request.getRemoteAddr());
String parameter;
if (\"GET\".equalsIgnoreCase(request.getMethod())) {
parameter = request.getQueryString();
} else if (new StandardServletMultipartResolver().isMultipart(request)) {
parameter = \"multipart\";
} else {
try {
parameter = new CustomHttpServletRequestWrapper(request).getBody();
} catch (Exception e) {
parameter = \"error_reading_body\";
}
}
mTrackLog.setParameter(parameter);
trackLogger.info(mTrackLog.toString());
}
}
}
在preHandle
方法里,每次请求开始时,我们创建一个MTrackLog
对象,记录下开始时间,然后把这个对象存到请求里。等请求处理完,在afterCompletion
方法里,我们再从请求里取出这个对象,补充上请求结束时间、请求方法、URL、请求IP和请求参数这些信息,最后把日志记录下来。这里获取请求参数的时候,会根据请求方法的不同来处理,如果是GET请求,直接取查询字符串;如果是文件上传这种multipart
请求,就标记为multipart
;其他情况就尝试读取请求体。
四、注册拦截器让其生效
写好拦截器后,还得注册一下,这样它才能在请求过程中起作用。注册拦截器的代码如下:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private RequestTrackInterceptor requestTrackInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestTrackInterceptor).addPathPatterns(\"/**\");
}
}
这段代码很简单,就是在配置类里把我们写好的RequestTrackInterceptor
注册到Spring的拦截器链里,并且设置它拦截所有的请求路径。
五、配置logback-spring.xml日志文件
最后,我们要配置一下日志文件,让日志能按我们的要求输出到指定文件里。在logback-spring.xml
里添加下面这些配置:
<!-- 跟踪日志输出到独立文件 -->
<appender name=\"TRACK_FILE\" class=\"ch.qos.logback.core.rolling.RollingFileAppender\">
<rollingPolicy class=\"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy\">
<fileNamePattern>${LOG_PATH}/track.%d{yyyyMMdd}.%i.log.gz</fileNamePattern>
<maxFileSize>20MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>1GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%msg%n</pattern> <!-- 输出格式为纯内容 JSON -->
</encoder>
<filter class=\"ch.qos.logback.classic.filter.LevelFilter\">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<logger name=\"TRACK_FILE_NAME\" level=\"INFO\" additivity=\"false\">
<appender-ref ref=\"TRACK_FILE\"/>
</logger>
这段配置的意思是,创建一个叫TRACK_FILE
的日志输出器,它会按照时间和文件大小滚动生成日志文件。日志的输出格式是纯JSON内容,并且只记录INFO级别的日志。然后把这个日志输出器和TRACK_FILE_NAME
这个日志记录器关联起来,这样日志就会输出到指定的文件里了。
六、看看示例输出日志长啥样
配置好之后,日志输出的样子大概是这样:
{\"url\":\"/api/user\", \"method\":\"GET\", \"cost\":102, \"level\":\"FAST\", \"ip\":\"192.168.1.101\", \"param\":\"id=1001\"}
{\"url\":\"/api/order\", \"method\":\"POST\", \"cost\":1580, \"level\":\"SERIOUS\", \"ip\":\"192.168.1.10\", \"param\":\"{\"userId\":10}\"}
从这些日志里,我们能清楚地看到每个请求的各种信息,还能根据耗时知道请求的性能情况。
七、总结一下
通过拦截器、自定义日志对象和logback多日志文件输出这一套组合拳,我们就实现了一个高性能、高可读性,还方便追踪分析的API日志追踪机制。这种方式在中大型项目,尤其是微服务场景里特别实用,每个服务都能独立输出访问日志。要是大家还想进一步拓展功能,还可以考虑加入TraceId做链路追踪,整合MDC实现日志链路穿透,或者配合ELK、SLS实现实时查询和报警这些功能。
要是这篇文章帮到了你,记得点赞、收藏,也欢迎关注我,以后还会分享更多Spring Boot的实战技巧!
还没有评论呢,快来抢沙发~