Skip to content

Commit

Permalink
Merge pull request #38 from ctroullis/master
Browse files Browse the repository at this point in the history
Jersey 2.x support
  • Loading branch information
kristofa committed Oct 11, 2014
2 parents ee07ede + 91721fa commit 5f5546e
Show file tree
Hide file tree
Showing 17 changed files with 782 additions and 9 deletions.
40 changes: 40 additions & 0 deletions brave-jersey2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# brave-jersey2 #

The brave-jersey2 module provides Jersey 2.x client and server support which will allow Brave to be used with any
existing Jersey 2.x application with minimal configuration.

The module contains 4 filters:

* `BraveContainerRequestFilter` - Intercepts incoming container requests and extracts any trace information from
the request header. Also sends sr annotations.
* `BraveContainerResponseFilter` - Intercepts outgoing container responses and sends ss annotations.
* `BraveClientRequestFilter` - Intercepts Jersey client requests and adds or forwards tracing information in the header.
Also sends cs annotations.
* `BraveClientResponseFilter` - Intercepts Jersey client responses and sends cr annotations. Also submits the completed span.

## Usage ##

For server side setup, you simply need to tell Jersey to scan the com.github.kristofa.brave.jersey2 package, and
the container filters will be picked up and registered automatically.

In your web.xml:

```xml
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
my.existing.packages,com.github.kristofa.brave.jersey2
</param-value>
</init-param>
```

For client side setup, you just have to register the client filters with your Jersey client before you make your request.

It should look something like:

Client client = ClientBuilder.newClient();
client.register(myBraveClientRequestFilter);
client.register(myBraveClientResponseFilter);



110 changes: 110 additions & 0 deletions brave-jersey2/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>brave</artifactId>
<groupId>com.github.kristofa</groupId>
<version>2.4-SNAPSHOT</version>
</parent>
<artifactId>brave-jersey2</artifactId>
<packaging>jar</packaging>
<name>brave-jersey2</name>
<description>
Jersey 2.x integration that uses the brave api to submit client and server side span information.
</description>
<url>https://github.com/kristofa/brave</url>
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jersey.version>2.13</jersey.version>
</properties>

<dependencies>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-interfaces</artifactId>
<version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-client</artifactId>
<version>2.4-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>

<!--Test Dependencies-->
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-inmemory</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-impl-spring</artifactId>
<version>2.4-SNAPSHOT</version>
<scope>test</scope>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
</plugin>
</plugins>
</build>


</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.github.kristofa.brave.jersey2;

import com.github.kristofa.brave.ClientTracer;
import com.github.kristofa.brave.client.ClientRequestInterceptor;
import com.github.kristofa.brave.client.spanfilter.SpanNameFilter;
import com.google.common.base.Optional;
import org.apache.commons.lang.Validate;

import javax.inject.Inject;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

/**
* Intercepts Jersey client requests and adds or forwards tracing information in the header.
* Also sends cs annotations.
*/
@Provider
public class BraveClientRequestFilter implements ClientRequestFilter {

private final ClientRequestInterceptor clientRequestInterceptor;
private final Optional<String> serviceName;

@Inject
public BraveClientRequestFilter(final ClientTracer clientTracer, final Optional<String> serviceName) {
Validate.notNull(clientTracer);
Validate.notNull(serviceName);
final Optional<SpanNameFilter> spanNameFilter = Optional.absent();
clientRequestInterceptor = new ClientRequestInterceptor(clientTracer, spanNameFilter);
this.serviceName = serviceName;
}

@Override
public void filter(ClientRequestContext clientRequestContext) throws IOException {
clientRequestInterceptor.handle(new JerseyClientRequestAdapter(clientRequestContext), serviceName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.kristofa.brave.jersey2;

import com.github.kristofa.brave.ClientTracer;
import com.github.kristofa.brave.client.ClientResponseInterceptor;
import com.google.common.base.Optional;
import org.apache.commons.lang.Validate;

import javax.inject.Inject;
import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientResponseContext;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

/**
* Intercepts Jersey client responses and sends cr annotations. Also submits the completed span.
*/
@Provider
public class BraveClientResponseFilter implements ClientResponseFilter {

private final ClientResponseInterceptor clientResponseInterceptor;

@Inject
public BraveClientResponseFilter(final ClientTracer clientTracer, final Optional<String> serviceName) {
Validate.notNull(clientTracer);
Validate.notNull(serviceName);
clientResponseInterceptor = new ClientResponseInterceptor(clientTracer);
}

@Override
public void filter(ClientRequestContext clientRequestContext, ClientResponseContext clientResponseContext) throws IOException {
clientResponseInterceptor.handle(new JerseyClientResponseAdapter(clientResponseContext));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package com.github.kristofa.brave.jersey2;

import com.github.kristofa.brave.BraveHttpHeaders;
import com.github.kristofa.brave.EndPointSubmitter;
import com.github.kristofa.brave.ServerTracer;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.net.URI;

/**
* Intercepts incoming container requests and extracts any trace information from the request header
* Also sends sr annotations.
*/
@Provider
public class BraveContainerRequestFilter implements ContainerRequestFilter {

private static Logger logger = LoggerFactory.getLogger(BraveContainerRequestFilter.class);

private final ServerTracer serverTracer;
private final EndPointSubmitter endPointSubmitter;

@Inject
public BraveContainerRequestFilter(ServerTracer serverTracer, EndPointSubmitter endPointSubmitter) {
this.serverTracer = serverTracer;
this.endPointSubmitter = endPointSubmitter;
}

@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
serverTracer.clearCurrentSpan();
UriInfo uriInfo = containerRequestContext.getUriInfo();
submitEndpoint(uriInfo);

TraceData traceData = getTraceDataFromHeaders(containerRequestContext);
if (Boolean.FALSE.equals(traceData.shouldBeTraced())) {
serverTracer.setStateNoTracing();
logger.debug("Not tracing request");
} else {
String spanName = getSpanName(traceData, uriInfo);
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();
}

private void submitEndpoint(UriInfo uri) {
if (!endPointSubmitter.endPointSubmitted()) {
URI baseUri = uri.getBaseUri();
String contextPath = getContextPath(uri);
String localAddr = baseUri.getHost();
int localPort = baseUri.getPort();
endPointSubmitter.submit(localAddr, localPort, contextPath);
logger.debug("Setting endpoint: addr: {}, port: {}, contextpath: {}", localAddr, localPort, contextPath);
}
}

private String getContextPath(UriInfo uri) {
final String contextPath = uri.getAbsolutePath().getPath();
String[] parts = StringUtils.split(contextPath, "/");
return parts[0];
}

private String getSpanName(TraceData traceData, UriInfo uri) {
if (traceData.getSpanName() == null || traceData.getSpanName().isEmpty()) {
return uri.getAbsolutePath().getPath();
}
return traceData.getSpanName();
}

private TraceData getTraceDataFromHeaders(ContainerRequestContext request) {
TraceData traceData = new TraceData();
traceData.setTraceId(longOrNull(request.getHeaderString(BraveHttpHeaders.TraceId.getName())));
traceData.setSpanId(longOrNull(request.getHeaderString(BraveHttpHeaders.SpanId.getName())));
traceData.setParentSpanId(longOrNull(request.getHeaderString(BraveHttpHeaders.ParentSpanId.getName())));
traceData.setShouldBeSampled(nullOrBoolean(request.getHeaderString(BraveHttpHeaders.Sampled.getName())));
traceData.setSpanName(request.getHeaderString(BraveHttpHeaders.SpanName.getName()));
return traceData;
}

private Boolean nullOrBoolean(String value) {
return (value == null) ? null : Boolean.valueOf(value);
}

private Long longOrNull(String value) {
if (value == null) {
return null;
}
return Long.parseLong(value, 16);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.github.kristofa.brave.jersey2;

import com.github.kristofa.brave.ServerTracer;

import javax.inject.Inject;
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 java.io.IOException;

/**
* Intercepts outgoing container responses and sends ss annotations.
*/
@Provider
public class BraveContainerResponseFilter implements ContainerResponseFilter {

private final ServerTracer serverTracer;

@Inject
public BraveContainerResponseFilter(ServerTracer serverTracer) {
this.serverTracer = serverTracer;
}

@Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
try {
serverTracer.setServerSend();
} finally {
serverTracer.clearCurrentSpan();
}
}
}
Loading

0 comments on commit 5f5546e

Please sign in to comment.