package io.dropwizard.jersey.filter;

import com.google.common.annotations.VisibleForTesting;
import io.dropwizard.util.Duration;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.util.function.Supplier;

This class adds an "X-Runtime" HTTP response header that includes the time taken to execute the request, in seconds (based on the implementation from Ruby on Rails).
See Also:
/** * This class adds an "X-Runtime" HTTP response header that includes the time * taken to execute the request, in seconds (based on the implementation from * Ruby on Rails). * * @see <a href="https://github.com/rack/rack/blob/2.0.0/lib/rack/runtime.rb">Rack::Runtime</a> */
@Provider @PreMatching public class RuntimeFilter implements ContainerRequestFilter, ContainerResponseFilter { private static final float NANOS_IN_SECOND = Duration.seconds(1).toNanoseconds(); private static final String RUNTIME_HEADER = "X-Runtime"; private static final String RUNTIME_PROPERTY = "io.dropwizard.jersey.filter.runtime"; private Supplier<Long> currentTimeProvider = System::nanoTime; @VisibleForTesting void setCurrentTimeProvider(Supplier<Long> currentTimeProvider) { this.currentTimeProvider = currentTimeProvider; } @Override public void filter(final ContainerRequestContext request) throws IOException { request.setProperty(RUNTIME_PROPERTY, currentTimeProvider.get()); } @Override public void filter(final ContainerRequestContext request, final ContainerResponseContext response) throws IOException { final Long startTime = (Long) request.getProperty(RUNTIME_PROPERTY); if (startTime != null) { final float seconds = (currentTimeProvider.get() - startTime) / NANOS_IN_SECOND; response.getHeaders().putSingle(RUNTIME_HEADER, String.format("%.6f", seconds)); } } }