package io.dropwizard.jersey.filter;

import java.io.IOException;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

import com.google.common.annotations.VisibleForTesting;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Strings;

This class adds a "X-Request-Id" HTTP response header and logs the following information: request method, request path, request ID, response status, response length (or -1 if not known).
See Also:
/** * This class adds a "X-Request-Id" HTTP response header and logs the following * information: request method, request path, request ID, response status, * response length (or -1 if not known). * * @see <a href="https://devcenter.heroku.com/articles/http-request-id">Heroku - HTTP Request IDs</a> */
@Provider @Priority(Priorities.USER) public class RequestIdFilter implements ContainerResponseFilter { private static final String REQUEST_ID = "X-Request-Id"; private Logger logger = LoggerFactory.getLogger(RequestIdFilter.class); @VisibleForTesting void setLogger(Logger logger) { this.logger = logger; } @Override public void filter(final ContainerRequestContext request, final ContainerResponseContext response) throws IOException { String id = request.getHeaderString(REQUEST_ID); if (Strings.isNullOrEmpty(id)) { id = generateRandomUuid().toString(); } logger.trace("method={} path={} request_id={} status={} length={}", request.getMethod(), request.getUriInfo().getPath(), id, response.getStatus(), response.getLength()); response.getHeaders().putSingle(REQUEST_ID, id); }
Generate a random UUID v4 that will perform reasonably when used by multiple threads under load.
See Also:
  • https://github.com/Netflix/netflix-commons/blob/v0.3.0/netflix-commons-util/src/main/java/com/netflix/util/concurrent/ConcurrentUUIDFactory.java
Returns:random UUID
/** * Generate a random UUID v4 that will perform reasonably when used by * multiple threads under load. * * @see https://github.com/Netflix/netflix-commons/blob/v0.3.0/netflix-commons-util/src/main/java/com/netflix/util/concurrent/ConcurrentUUIDFactory.java * @return random UUID */
private static UUID generateRandomUuid() { final Random rnd = ThreadLocalRandom.current(); long mostSig = rnd.nextLong(); long leastSig = rnd.nextLong(); // Identify this as a version 4 UUID, that is one based on a random value. mostSig &= 0xffffffffffff0fffL; mostSig |= 0x0000000000004000L; // Set the variant identifier as specified for version 4 UUID values. The two // high order bits of the lower word are required to be one and zero, respectively. leastSig &= 0x3fffffffffffffffL; leastSig |= 0x8000000000000000L; return new UUID(mostSig, leastSig); } }