如何在 JAX-RS 过滤器中记录请求处理时间

coo*_*lsv 2 jax-rs quarkus

我有 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);
    }

}
Run Code Online (Sandbox Code Playgroud)

它在第一种方法中工作正常,其中当前时间戳写入requestStartTime. 但是,似乎第二种方法有自己的requestStartTime变量副本,因为它是第二种方法,它始终等于零。所以我无法计算变量之间的差异。我可以做什么来记录请求处理时间?

Lor*_*uro 7

由于您在同一个类中实现这两个ContainerRequestFilter实例ContainerResponseFilter,因此似乎创建了 2 个不同的实例,因此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相反,您可以将开始时间保存在on的属性上ContainerRequestFilter.filter(),然后获取它并在 on 上使用它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");
    }
}
Run Code Online (Sandbox Code Playgroud)