Skip to content

Commit

Permalink
OkHttp Request and Response Interceptor for cs/cr annotations (openzi…
Browse files Browse the repository at this point in the history
  • Loading branch information
tburch authored and adriancole committed May 18, 2016
1 parent 2d2dd3d commit ac05b7b
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 0 deletions.
16 changes: 16 additions & 0 deletions brave-okhttp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# brave-okhttp #

This implementation makes it easy to integrate with brave to catch/trace [OkHttp](https://github.com/square/okhttp) requests. The `BraveOkHttpRequestResponseInterceptor` OkHttp [`Interceptor`](http://square.github.io/okhttp/3.x/okhttp/index.html?okhttp3/Interceptor.html) implementation will start a new Span and submit a `cs` (client sent) annotation and then submit `cr` (client received) annotation after the request is received.

Example of configuring the interceptor with OkHttp:

```
import com.github.kristofa.brave.okhttp.BraveOkHttpRequestResponseInterceptor;
import okhttp3.OkHttpClient;
...
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new BraveOkHttpRequestResponseInterceptor(...))
.build();
```
49 changes: 49 additions & 0 deletions brave-okhttp/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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">
<parent>
<artifactId>brave</artifactId>
<groupId>com.github.kristofa</groupId>
<version>3.7.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>brave-okhttp</artifactId>

<description>OkHttp request and response interceptor implementation</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>
<okhttp.version>3.2.0</okhttp.version>
</properties>

<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>brave-http</artifactId>
<version>3.7.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>${okhttp.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.github.kristofa.brave.okhttp;


import com.github.kristofa.brave.ClientRequestInterceptor;
import com.github.kristofa.brave.ClientResponseInterceptor;
import com.github.kristofa.brave.http.HttpClientRequestAdapter;
import com.github.kristofa.brave.http.HttpClientResponseAdapter;
import com.github.kristofa.brave.http.SpanNameProvider;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;

public class BraveOkHttpRequestResponseInterceptor implements Interceptor {

private final ClientRequestInterceptor clientRequestInterceptor;
private final ClientResponseInterceptor clientResponseInterceptor;
private final SpanNameProvider spanNameProvider;

public BraveOkHttpRequestResponseInterceptor(ClientRequestInterceptor requestInterceptor, ClientResponseInterceptor responseInterceptor, SpanNameProvider spanNameProvider) {
this.spanNameProvider = spanNameProvider;
this.clientRequestInterceptor = requestInterceptor;
this.clientResponseInterceptor = responseInterceptor;
}

@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
OkHttpRequest okHttpRequest = new OkHttpRequest(builder, request);
clientRequestInterceptor.handle(new HttpClientRequestAdapter(okHttpRequest, spanNameProvider));
Response response = chain.proceed(builder.build());
clientResponseInterceptor.handle(new HttpClientResponseAdapter(new OkHttpResponse(response)));
return response;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.github.kristofa.brave.okhttp;


import com.github.kristofa.brave.http.HttpClientRequest;
import okhttp3.Request;

import java.net.URI;

class OkHttpRequest implements HttpClientRequest {

private final Request.Builder requestBuilder;
private final Request request;

OkHttpRequest(Request.Builder requestBuilder, Request request) {
this.requestBuilder = requestBuilder;
this.request = request;
}

@Override
public void addHeader(String header, String value) {
requestBuilder.addHeader(header, value);
}

@Override
public String getHttpMethod() {
return request.method();
}

@Override
public URI getUri() {
return request.url().uri();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.kristofa.brave.okhttp;


import com.github.kristofa.brave.http.HttpResponse;
import okhttp3.Response;

class OkHttpResponse implements HttpResponse {

private final Response response;

OkHttpResponse(Response response) {
this.response = response;
}

@Override
public int getHttpStatusCode() {
return response.code();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
package com.github.kristofa.brave.okhttp;

import com.github.kristofa.brave.ClientRequestInterceptor;
import com.github.kristofa.brave.ClientResponseInterceptor;
import com.github.kristofa.brave.ClientTracer;
import com.github.kristofa.brave.SpanId;
import com.github.kristofa.brave.TraceKeys;
import com.github.kristofa.brave.http.BraveHttpHeaders;
import com.github.kristofa.brave.http.DefaultSpanNameProvider;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.IOException;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

public class BraveOkHttpRequestResponseInterceptorTest {

private static final Long SPAN_ID = 151864l;
private static final Long TRACE_ID = 8494864l;
private static final String HTTP_METHOD_GET = "GET";

@Rule
public final ExpectedException thrown = ExpectedException.none();
@Rule
public final MockWebServer server = new MockWebServer();

@Mock(answer = Answers.RETURNS_SMART_NULLS)
private ClientTracer clientTracer;

private SpanId spanId;
private OkHttpClient client;

@Before
public void setup() throws IOException {
MockitoAnnotations.initMocks(this);
this.spanId = SpanId.builder().spanId(SPAN_ID).traceId(TRACE_ID).parentId(null).build();
this.client = new OkHttpClient.Builder()
.addInterceptor(new BraveOkHttpRequestResponseInterceptor(new ClientRequestInterceptor(clientTracer), new ClientResponseInterceptor(clientTracer), new DefaultSpanNameProvider()))
.build();
}

@Test
public void testTracingTrue() throws IOException, InterruptedException {
when(clientTracer.startNewSpan(HTTP_METHOD_GET)).thenReturn(spanId);

String url = "http://localhost:" + server.getPort() + "/foo";
Request request = new Request.Builder()
.url(url)
.build();

server.enqueue(new MockResponse()
.setBody("bar")
.setResponseCode(200)
);

Response response = client.newCall(request).execute();

assertEquals(200, response.code());

InOrder inOrder = inOrder(clientTracer);
inOrder.verify(clientTracer).startNewSpan(HTTP_METHOD_GET);
inOrder.verify(clientTracer).submitBinaryAnnotation(TraceKeys.HTTP_URL, url);
inOrder.verify(clientTracer).setClientSent();
inOrder.verify(clientTracer).setClientReceived();
verifyNoMoreInteractions(clientTracer);

RecordedRequest serverRequest = server.takeRequest();
assertEquals(HTTP_METHOD_GET, serverRequest.getMethod());
assertEquals("1", serverRequest.getHeader(BraveHttpHeaders.Sampled.getName()));
assertEquals(Long.toString(TRACE_ID, 16), serverRequest.getHeader(BraveHttpHeaders.TraceId.getName()));
assertEquals(Long.toString(SPAN_ID, 16), serverRequest.getHeader(BraveHttpHeaders.SpanId.getName()));
}

@Test
public void testTracingTrueHttpNoOk() throws IOException, InterruptedException {
when(clientTracer.startNewSpan(HTTP_METHOD_GET)).thenReturn(spanId);

String url = "http://localhost:" + server.getPort() + "/foo";
Request request = new Request.Builder()
.url(url)
.build();

server.enqueue(new MockResponse()
.setBody("bar")
.setResponseCode(400)
);

Response response = client.newCall(request).execute();

assertEquals(400, response.code());

InOrder inOrder = inOrder(clientTracer);
inOrder.verify(clientTracer).startNewSpan(HTTP_METHOD_GET);
inOrder.verify(clientTracer).submitBinaryAnnotation(TraceKeys.HTTP_URL, url);
inOrder.verify(clientTracer).setClientSent();
inOrder.verify(clientTracer).submitBinaryAnnotation(TraceKeys.HTTP_STATUS_CODE, "400");
inOrder.verify(clientTracer).setClientReceived();
verifyNoMoreInteractions(clientTracer);

RecordedRequest serverRequest = server.takeRequest();
assertEquals(HTTP_METHOD_GET, serverRequest.getMethod());
assertEquals("1", serverRequest.getHeader(BraveHttpHeaders.Sampled.getName()));
assertEquals(Long.toString(TRACE_ID, 16), serverRequest.getHeader(BraveHttpHeaders.TraceId.getName()));
assertEquals(Long.toString(SPAN_ID, 16), serverRequest.getHeader(BraveHttpHeaders.SpanId.getName()));
}

@Test
public void testTracingFalse() throws IOException, InterruptedException {
when(clientTracer.startNewSpan(HTTP_METHOD_GET)).thenReturn(null);

String url = "http://localhost:" + server.getPort() + "/foo";
Request request = new Request.Builder()
.url(url)
.build();

server.enqueue(new MockResponse()
.setBody("bar")
);

Response response = client.newCall(request).execute();

assertEquals(200, response.code());

InOrder inOrder = inOrder(clientTracer);
inOrder.verify(clientTracer).startNewSpan(HTTP_METHOD_GET);
inOrder.verify(clientTracer).setClientReceived();
verifyNoMoreInteractions(clientTracer);

RecordedRequest serverRequest = server.takeRequest();
assertEquals(HTTP_METHOD_GET, serverRequest.getMethod());
assertEquals("0", serverRequest.getHeader(BraveHttpHeaders.Sampled.getName()));
}

@Test
public void testQueryParams() throws IOException, InterruptedException {
when(clientTracer.startNewSpan(HTTP_METHOD_GET)).thenReturn(spanId);

String url = "http://localhost:" + server.getPort() + "/foo?z=2&yAA";
Request request = new Request.Builder()
.url(url)
.build();

server.enqueue(new MockResponse()
.setBody("bar")
);

Response response = client.newCall(request).execute();

assertEquals(200, response.code());

InOrder inOrder = inOrder(clientTracer);
inOrder.verify(clientTracer).startNewSpan(HTTP_METHOD_GET);
inOrder.verify(clientTracer).submitBinaryAnnotation(TraceKeys.HTTP_URL, url);
inOrder.verify(clientTracer).setClientSent();
inOrder.verify(clientTracer).setClientReceived();
verifyNoMoreInteractions(clientTracer);

RecordedRequest serverRequest = server.takeRequest();
assertEquals(HTTP_METHOD_GET, serverRequest.getMethod());
assertEquals("1", serverRequest.getHeader(BraveHttpHeaders.Sampled.getName()));
assertEquals(Long.toString(TRACE_ID, 16), serverRequest.getHeader(BraveHttpHeaders.TraceId.getName()));
assertEquals(Long.toString(SPAN_ID, 16), serverRequest.getHeader(BraveHttpHeaders.SpanId.getName()));
}

}
13 changes: 13 additions & 0 deletions brave-okhttp/src/test/resources/log4j2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<module>brave-spring-resttemplate-interceptors</module>
<module>brave-mysql</module>
<module>brave-web-servlet-filter</module>
<module>brave-okhttp</module>
</modules>

<distributionManagement>
Expand Down

0 comments on commit ac05b7b

Please sign in to comment.