-
Notifications
You must be signed in to change notification settings - Fork 713
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #38 from ctroullis/master
Jersey 2.x support
- Loading branch information
Showing
17 changed files
with
782 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
38 changes: 38 additions & 0 deletions
38
brave-jersey2/src/main/java/com/github/kristofa/brave/jersey2/BraveClientRequestFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
brave-jersey2/src/main/java/com/github/kristofa/brave/jersey2/BraveClientResponseFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
104 changes: 104 additions & 0 deletions
104
...-jersey2/src/main/java/com/github/kristofa/brave/jersey2/BraveContainerRequestFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
...jersey2/src/main/java/com/github/kristofa/brave/jersey2/BraveContainerResponseFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |
Oops, something went wrong.