com.github.kristofa.brave.resteasy.BravePreProcessInterceptor Maven / Gradle / Ivy
package com.github.kristofa.brave.resteasy;
import java.util.List;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;
import org.jboss.resteasy.core.ResourceMethod;
import org.jboss.resteasy.core.ServerResponse;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.interception.PreProcessInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.github.kristofa.brave.BraveHttpHeaders;
import com.github.kristofa.brave.EndPointSubmitter;
import com.github.kristofa.brave.ServerTracer;
/**
* Rest Easy {@link PreProcessInterceptor} that will:
*
* - Set {@link EndPoint} information for our service in case it is not set yet.
* - Get trace data (trace id, span id, parent span id) from http headers and initialize state for request + submit 'server
* received' for request.
* - If no trace information is submitted we will start a new span. In that case it means client does not support tracing
* and should be adapted.
*
*
* @author kristof
*/
@Component
@Provider
@ServerInterceptor
public class BravePreProcessInterceptor implements PreProcessInterceptor {
private final static Logger LOGGER = LoggerFactory.getLogger(BravePreProcessInterceptor.class);
private final EndPointSubmitter endPointSubmitter;
private final ServerTracer serverTracer;
@Context
HttpServletRequest servletRequest;
/**
* Creates a new instance.
*
* @param endPointSubmitter {@link EndPointSubmitter}. Should not be null.
* @param serverTracer {@link ServerTracer}. Should not be null.
* @param randomGenerator Random generator.
*/
@Autowired
public BravePreProcessInterceptor(final EndPointSubmitter endPointSubmitter, final ServerTracer serverTracer) {
Validate.notNull(endPointSubmitter);
Validate.notNull(serverTracer);
this.endPointSubmitter = endPointSubmitter;
this.serverTracer = serverTracer;
}
/**
* {@inheritDoc}
*/
@Override
public ServerResponse preProcess(final HttpRequest request, final ResourceMethod method) throws Failure,
WebApplicationException {
submitEndpoint();
serverTracer.clearCurrentSpan();
final TraceData traceData = getTraceData(request);
if (Boolean.FALSE.equals(traceData.shouldBeTraced())) {
serverTracer.setStateNoTracing();
LOGGER.debug("Received indication that we should NOT trace.");
} else {
String spanName = getSpanName(request, traceData);
if (traceData.getTraceId() != null && traceData.getSpanId() != null) {
LOGGER.debug("Received span information as part of request.");
serverTracer.setStateCurrentTrace(traceData.getTraceId(), traceData.getSpanId(),
traceData.getParentSpanId(), spanName);
} else {
LOGGER.debug("Received no span state.");
serverTracer.setStateUnknown(spanName);
}
serverTracer.setServerReceived();
}
return null;
}
private String getSpanName(HttpRequest request, TraceData traceData) {
if (StringUtils.isNotBlank(traceData.getSpanName())) {
return traceData.getSpanName();
} else {
return request.getPreprocessedPath();
}
}
private void submitEndpoint() {
if (!endPointSubmitter.endPointSubmitted()) {
final String localAddr = servletRequest.getLocalAddr();
final int localPort = servletRequest.getLocalPort();
final String contextPath = servletRequest.getContextPath();
LOGGER.debug("Setting endpoint: addr: {}, port: {}, contextpath: {}", localAddr, localPort, contextPath);
endPointSubmitter.submit(localAddr, localPort, contextPath);
}
}
private TraceData getTraceData(final HttpRequest request) {
final HttpHeaders httpHeaders = request.getHttpHeaders();
final MultivaluedMap requestHeaders = httpHeaders.getRequestHeaders();
final TraceData traceData = new TraceData();
for (final Entry> headerEntry : requestHeaders.entrySet()) {
LOGGER.debug("{}={}", headerEntry.getKey(), headerEntry.getValue());
if (BraveHttpHeaders.TraceId.getName().equalsIgnoreCase(headerEntry.getKey())) {
traceData.setTraceId(getFirstLongValueFor(headerEntry));
} else if (BraveHttpHeaders.SpanId.getName().equalsIgnoreCase(headerEntry.getKey())) {
traceData.setSpanId(getFirstLongValueFor(headerEntry));
} else if (BraveHttpHeaders.ParentSpanId.getName().equalsIgnoreCase(headerEntry.getKey())) {
traceData.setParentSpanId(getFirstLongValueFor(headerEntry));
} else if (BraveHttpHeaders.Sampled.getName().equalsIgnoreCase(headerEntry.getKey())) {
traceData.setShouldBeSampled(getFirstBooleanValueFor(headerEntry));
} else if (BraveHttpHeaders.SpanName.getName().equalsIgnoreCase(headerEntry.getKey())) {
traceData.setSpanName(getFirstStringValueFor(headerEntry));
}
}
return traceData;
}
private Long getFirstLongValueFor(final Entry> headerEntry) {
final String firstStringValueFor = getFirstStringValueFor(headerEntry);
return firstStringValueFor == null ? null : Long.valueOf(firstStringValueFor);
}
private Boolean getFirstBooleanValueFor(final Entry> headerEntry) {
final String firstStringValueFor = getFirstStringValueFor(headerEntry);
return firstStringValueFor == null ? null : Boolean.valueOf(firstStringValueFor);
}
private String getFirstStringValueFor(final Entry> headerEntry) {
final List values = headerEntry.getValue();
if (values != null && values.size() > 0) {
return headerEntry.getValue().get(0);
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy