@Component
public class RequestResponseStoringFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
long start = System.currentTimeMillis();
try {
chain.doFilter(req, resp);
} finally {
// Measure elapsed time
long elapsed = System.currentTimeMillis() - start;
// store request data and store response data in a DB
.....
}
}
@Override
public void destroy() {}
@Override
public void init(FilterConfig arg0) throws ServletException {}
}
3条答案
按热度按时间wmvff8tz1#
第一个问题是我应该在实体中使用什么类型的请求和响应(字符串、blob等)
它主要取决于数据库供应商和请求/响应长度。
对于某些供应商,字符串可能会受到限制,因此需要blob。另一方面,blob上的匹配速度较慢。
另一种选择是使用nosql格式,比如json。
第二个问题,如何获取请求、响应及其控制器名称来创建要保存到数据库的实体?
其实有好几种方法。
您可以利用内置的SpringBootHTTP跟踪特性,但它有一个限制:请求/响应的发布/接收不可用。
5.8. http跟踪
可以通过在应用程序的配置中提供httptracerepository类型的bean来启用http跟踪。为了方便起见,SpringBoot提供了一个inmemoryhttptracerepository,默认情况下,它存储最后100次请求-响应交换的跟踪。inmemoryhttptracerepository与其他跟踪解决方案相比是有限的,我们建议只在开发环境中使用它。对于生产环境,建议使用生产就绪跟踪或可观察性解决方案,如zipkin或springcloudsleuth。或者,创建满足您需要的httptracerepository。
httptrace端点可用于获取有关存储在httptracerepository中的请求-响应交换的信息。
5.8.1. 自定义http跟踪
要自定义每个跟踪中包含的项,请使用management.trace.http.include配置属性。对于高级定制,请考虑注册自己的httpexchangetracer实现。
另一种方法是为请求/响应实现一个过滤器并登录它。
例如:
最后,是否可以计算控制器的响应时间(在控制器中花费的时间)?
实现过滤器的方法如上所示。
httptrace端点方式提供了
timeTaken
现场。fiy,以下是httptrace示例的内容:
jdzmm42g2#
这是对其他答案的扩展,但我认为它需要一个单独的答案。
如果您正在拉入springbootstarterweb,那么您已经在拉入springaop了。如果你要走点切割路线,我强烈建议你只使用测微计
@Timed
随附的注解spring-boot-starter-actuator
. 我已经写了很多次我自己的度量切入点,但是如果你只是在计时和成功与失败的计数之后,@Timed
效果很好。我还强烈建议使用时间序列数据库(例如inflox)来存储响应时间和其他性能指标。将原始有效负载和其他可能的审计问题保存在单独的数据库中。有一些非常强大的事情,你可以做的涌入和运行格拉法纳或chronograf之上。毫无疑问,我现在的公司多年来做的最好的事情之一就是采用influx/chronograf。
关于请求/响应捕获,我的工作流程中有一个奇怪的边缘案例,其中http跟踪无法满足某些硬需求。您可以使用
ContentCachingRequestWrapper
然后您可以通过以下方式访问它们:注意
OncePerRequestFilter
,我发现我的筛选器多次为同一请求触发。这就避免了这种情况。i2loujxw3#
添加此依赖项:
然后,创建一个
Around
控制器方法执行方面:至于持久化:首先,得到req和resp,如下所示:
那就看你到底想坚持什么了。对于具有简单字段的类,我会使用
varchar
,记住要覆盖他们的toString
方法。