我有JAX-RS Web应用程序,我想记录从获取请求到响应的时间。在Spring Boot中使用servlet过滤器很容易。但是我的应用程序中的过滤器无法正常运行:
@Provider
public class RequestLogFilter implements ContainerRequestFilter, ContainerResponseFilter {
private long requestStartTime;
@Override
public void filter(ContainerRequestContext requestContext) {
requestStartTime = System.currentTimeMillis();
}
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
long requestFinishTime = System.currentTimeMillis();
System.out.println(requestFinishTime - requestStartTime);
}
}
在第一种方法中工作正常,当前时间戳记写在requestStartTime
中。但是,似乎第二个方法拥有自己的requestStartTime
变量副本,因为第二个方法始终等于零。所以我不能计算变量之间的差异。我该怎么办才能记录请求处理时间?
答案 0 :(得分:3)
由于您是在同一类中同时实现ContainerRequestFilter
和ContainerResponseFilter
,因此似乎创建了两个不同的实例,因此变量requestStartTime
在两个实例之间是不同的。>
此问题已在Eclipse Jersey项目上报告,并认为是错误,已解决,请参见https://github.com/eclipse-ee4j/jersey/issues/3796。
这里是整个讨论区:https://github.com/eclipse-ee4j/jaxrs-api/issues/605。
有论据认为此行为不符合JAX-RS规范(第4.1节):
默认情况下,每个提供程序类的单个实例都被实例化 每个JAX-RS应用程序
但是Quarkus使用RESTEasy,所以我猜它不包含该修补程序。
无论如何,即使创建了一个实例(例如,使用注释@Singleton
),您仍不应使用实例变量来保留开始时间,因为并发请求会覆盖它(感谢@areus指出这一点)。
相反,您可以将开始时间保存在ContainerRequestContext
上ContainerRequestFilter.filter()
的属性中,然后在ContainerResponseFilter.filter()
上获取并使用它:
@Provider
public class RequestLogFilter implements ContainerRequestFilter, ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext) {
long requestStartTime = System.nanoTime();
requestContext.setProperty("requestStartTime", requestStartTime);
}
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
long requestStartTime = (long) requestContext.getProperty("requestStartTime");
long requestFinishTime = System.nanoTime();
long duration = requestFinishTime - requestStartTime;
System.out.println("duration: " + TimeUnit.NANOSECONDS.toMillis(duration) + " ms");
}
}
答案 1 :(得分:2)
实际上,由于MicroProfile Metrics API,Quarkus内置了类似的东西:
将SmallRye Metrics扩展名(quarkus-smallrye-metrics)添加到pom.xml
默认情况下应启用此功能,但可以通过在application.properties中添加以下内容来显式启用RestEasy / JAX-RS度量标准进行注册:
quarkus.smallrye-metrics.extensions.enabled = true
度量标准(#次调用,每个过程花费的时间)将添加到/ metrics端点。一旦调用端点,指标就会显示出来。