-
Notifications
You must be signed in to change notification settings - Fork 714
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reduces the parser hooks to parity with how responses are handled (#406)
Response can be either error or success. This aligns parsing strategy with handling strategy, which reduces duplication particularly around parsing status codes.
- Loading branch information
1 parent
32e87a3
commit 40bd33e
Showing
11 changed files
with
193 additions
and
114 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
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
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
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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,61 @@ | |||
package brave.http; | |||
|
|||
import brave.Span; | |||
import brave.internal.Nullable; | |||
import zipkin.Constants; | |||
import zipkin.TraceKeys; | |||
|
|||
/** | |||
* Provides reasonable defaults for the data contained in http spans. Subclass to customize, | |||
* for example, to add tags based on user ID. | |||
*/ | |||
public class HttpParser { | |||
/** Returns the span name of the request. Defaults to the http method. */ | |||
public <Req> String spanName(HttpAdapter<Req, ?> adapter, Req req) { | |||
return adapter.method(req); | |||
} | |||
|
|||
/** By default, this adds the {@link TraceKeys#HTTP_PATH}. */ | |||
public <Req> void requestTags(HttpAdapter<Req, ?> adapter, Req req, Span span) { | |||
String path = adapter.path(req); | |||
if (path != null) span.tag(TraceKeys.HTTP_PATH, path); | |||
} | |||
|
|||
/*** | |||
* By default, this adds {@link TraceKeys#HTTP_STATUS_CODE} when it is not 2xx. If there's an | |||
* exception or the status code is neither 2xx nor 3xx, it adds {@link Constants#ERROR}. | |||
* | |||
* <p>Note: Either the response or error parameters may be null, but not both | |||
* | |||
* @see #parseError(Integer, Throwable) | |||
*/ | |||
public <Resp> void responseTags(HttpAdapter<?, Resp> adapter, @Nullable Resp res, | |||
@Nullable Throwable error, Span span) { | |||
Integer httpStatus = res != null ? adapter.statusCode(res) : null; | |||
if (httpStatus != null && (httpStatus < 200 || httpStatus > 299)) { | |||
span.tag(TraceKeys.HTTP_STATUS_CODE, String.valueOf(httpStatus)); | |||
} | |||
String message = parseError(httpStatus, error); | |||
if (message != null) span.tag(Constants.ERROR, message); | |||
} | |||
|
|||
/** | |||
* Returns the {@link TraceKeys#HTTP_STATUS_CODE} when it is not 2xx. If there's an | |||
* exception or the status code is neither 2xx nor 3xx, it adds {@link Constants#ERROR}. | |||
* | |||
* <p>Note: Either the httpStatus or error parameters may be null, but not both | |||
* | |||
* @see Constants#ERROR | |||
*/ | |||
@Nullable protected String parseError(@Nullable Integer httpStatus, @Nullable Throwable error) { | |||
if (error != null) { | |||
String message = error.getMessage(); | |||
return message != null ? message : error.getClass().getSimpleName(); | |||
} | |||
if (httpStatus == null) return null; | |||
return httpStatus < 200 || httpStatus > 399 ? String.valueOf(httpStatus) : null; | |||
} | |||
|
|||
HttpParser() { | |||
} | |||
} |
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
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
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
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
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 | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,72 @@ | |||
package brave.http; | |||
|
|||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.mockito.Mock; | |||
import org.mockito.runners.MockitoJUnitRunner; | |||
import zipkin.TraceKeys; | |||
|
|||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.never; | |||
import static org.mockito.Mockito.verify; | |||
import static org.mockito.Mockito.when; | |||
|
|||
@RunWith(MockitoJUnitRunner.class) | |||
public class HttpParserTest { | |||
@Mock HttpClientAdapter<Object, Object> adapter; | |||
@Mock brave.Span span; | |||
Object request = new Object(); | |||
Object response = new Object(); | |||
HttpParser parser = new HttpParser(); | |||
|
|||
@Test public void spanName_isMethod() { | |||
when(adapter.method(request)).thenReturn("GET"); | |||
|
|||
assertThat(parser.spanName(adapter, request)) | |||
.isEqualTo("GET"); | |||
} | |||
|
|||
@Test public void requestTags_addsPath() { | |||
when(adapter.path(request)).thenReturn("/foo"); | |||
|
|||
parser.requestTags(adapter, request, span); | |||
|
|||
verify(span).tag(TraceKeys.HTTP_PATH, "/foo"); | |||
} | |||
|
|||
@Test public void requestTags_doesntCrashOnNullPath() { | |||
parser.requestTags(adapter, request, span); | |||
|
|||
verify(span, never()).tag(TraceKeys.HTTP_PATH, null); | |||
} | |||
|
|||
@Test public void responseTags_tagsErrorOnResponseCode() { | |||
when(adapter.statusCode(response)).thenReturn(400); | |||
|
|||
parser.responseTags(adapter, response, null, span); | |||
|
|||
verify(span).tag("error", "400"); | |||
} | |||
|
|||
@Test public void responseTags_tagsErrorFromException() { | |||
parser.responseTags(adapter, response, new RuntimeException("drat"), span); | |||
|
|||
verify(span).tag("error", "drat"); | |||
} | |||
|
|||
@Test public void responseTags_tagsErrorPrefersExceptionVsResponseCode() { | |||
when(adapter.statusCode(response)).thenReturn(400); | |||
|
|||
parser.responseTags(adapter, response, new RuntimeException("drat"), span); | |||
|
|||
verify(span).tag("error", "drat"); | |||
} | |||
|
|||
@Test public void responseTags_tagsErrorOnExceptionEvenIfStatusOk() { | |||
when(adapter.statusCode(response)).thenReturn(200); | |||
|
|||
parser.responseTags(adapter, response, new RuntimeException("drat"), span); | |||
|
|||
verify(span).tag("error", "drat"); | |||
} | |||
} |
Oops, something went wrong.