Merge pull request #39 from DataDog/tyler/non-null-headers

Ensure headers are never null
This commit is contained in:
Tyler Benson 2017-07-10 07:44:18 -07:00 committed by GitHub
commit 86db1632a4
6 changed files with 41 additions and 32 deletions

View File

@ -37,3 +37,7 @@ test {
} }
test.dependsOn project(':dd-java-agent').shadowJar test.dependsOn project(':dd-java-agent').shadowJar
parent.subprojects.collect { it.tasks.withType(Test) } each {
test.shouldRunAfter it
}

View File

@ -1,4 +1,5 @@
plugins { plugins {
id 'groovy'
id "com.github.johnrengelman.shadow" version "2.0.1" id "com.github.johnrengelman.shadow" version "2.0.1"
} }

View File

@ -22,8 +22,13 @@ import java.util.*;
*/ */
public class DDTracer implements io.opentracing.Tracer { public class DDTracer implements io.opentracing.Tracer {
public final static String CURRENT_VERSION = DDTracer.class.getPackage().getImplementationVersion();
public final static String JAVA_VERSION = System.getProperty("java.version", "unknown"); public final static String JAVA_VERSION = System.getProperty("java.version", "unknown");
public final static String CURRENT_VERSION;
static {
String version = DDTracer.class.getPackage().getImplementationVersion();
CURRENT_VERSION = version != null ? version : "unknown";
}
/** /**
* Writer is an charge of reporting traces and spans to the desired endpoint * Writer is an charge of reporting traces and spans to the desired endpoint

View File

@ -1,7 +1,4 @@
package com.datadog.trace package com.datadoghq.trace
import com.datadoghq.trace.DDSpan
import com.datadoghq.trace.DDSpanContext
class SpanFactory { class SpanFactory {
static def newSpanOf(long timestampMicro) { static def newSpanOf(long timestampMicro) {

View File

@ -1,10 +1,10 @@
package com.datadoghq.trace.writer package com.datadoghq.trace.writer
import com.datadog.trace.SpanFactory import com.datadoghq.trace.SpanFactory
import com.datadoghq.trace.DDSpan import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.ObjectMapper
import ratpack.http.Headers
import ratpack.http.MediaType import ratpack.http.MediaType
import spock.lang.AutoCleanup
import spock.lang.Specification import spock.lang.Specification
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
@ -54,11 +54,13 @@ class DDApiTest extends Specification {
def "content is sent as JSON"() { def "content is sent as JSON"() {
setup: setup:
def requestContentType = new AtomicReference<MediaType>() def requestContentType = new AtomicReference<MediaType>()
def requestHeaders = new AtomicReference<Headers>()
def requestBody = new AtomicReference<String>() def requestBody = new AtomicReference<String>()
def agent = ratpack { def agent = ratpack {
handlers { handlers {
put("v0.3/traces") { put("v0.3/traces") {
requestContentType.set(request.contentType) requestContentType.set(request.contentType)
requestHeaders.set(request.headers)
request.body.then { request.body.then {
requestBody.set(it.text) requestBody.set(it.text)
response.send() response.send()
@ -71,47 +73,47 @@ class DDApiTest extends Specification {
expect: expect:
client.sendTraces(traces) client.sendTraces(traces)
requestContentType.get().type == APPLICATION_JSON requestContentType.get().type == APPLICATION_JSON
areEqual(requestBody.get(), expectedRequestBody) requestHeaders.get().get("Datadog-Meta-Lang") == "java"
requestHeaders.get().get("Datadog-Meta-Lang-Version") == System.getProperty("java.version", "unknown");
requestHeaders.get().get("Datadog-Meta-Tracer-Version") == "unknown"
convert(requestBody.get()) == expectedRequestBody
cleanup: cleanup:
agent.close() agent.close()
// Populate thread info dynamically as it is different when run via gradle vs idea.
where: where:
traces | expectedRequestBody traces | expectedRequestBody
[] | '[]' [] | []
[SpanFactory.newSpanOf(1L)] | '''[{ [SpanFactory.newSpanOf(1L)] | [new TreeMap<>([
"duration":0, "duration":0,
"error":0, "error":0,
"meta":{"thread-name":"main","thread-id":"1"}, "meta":["thread-name":Thread.currentThread().getName(),"thread-id":"${Thread.currentThread().id}"],
"name":"fakeOperation", "name":"fakeOperation",
"parent_id":0, "parent_id":0,
"resource":"fakeResource" "resource":"fakeResource",
"service":"fakeService", "service":"fakeService",
"span_id":1, "span_id":1,
"start":1000, "start":1000,
"trace_id":1, "trace_id":1,
"type":"fakeType", "type":"fakeType"
}]''' ])]
[SpanFactory.newSpanOf(100L)] | '''[{ [SpanFactory.newSpanOf(100L)] | [new TreeMap<>([
"duration":0, "duration":0,
"error":0, "error":0,
"meta":{"thread-name":"main","thread-id":"1"}, "meta":["thread-name":Thread.currentThread().getName(),"thread-id":"${Thread.currentThread().id}"],
"name":"fakeOperation", "name":"fakeOperation",
"parent_id":0, "parent_id":0,
"resource":"fakeResource" "resource":"fakeResource",
"service":"fakeService", "service":"fakeService",
"span_id":1, "span_id":1,
"start":100000, "start":100000,
"trace_id":1, "trace_id":1,
"type":"fakeType", "type":"fakeType"
}]''' ])]
} }
static List<TreeMap<String, Object>> convert(String json) {
static void areEqual(String json1, String json2) { return mapper.readValue(json, new TypeReference<List<TreeMap<String, Object>>>() {})
def tree1 = mapper.readTree json1
def tree2 = mapper.readTree json2
assert tree1.equals(tree2)
} }
} }

View File

@ -8,6 +8,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -124,15 +125,14 @@ public class DDSpanBuilderTest {
assertThat(span.getStartTime()).isEqualTo(expectedTimestamp * 1000L); assertThat(span.getStartTime()).isEqualTo(expectedTimestamp * 1000L);
// auto-timestamp in nanoseconds // auto-timestamp in nanoseconds
long tick = System.currentTimeMillis() * 1000 * 1000L; long tick = System.currentTimeMillis();
span = tracer span = tracer
.buildSpan(expectedName) .buildSpan(expectedName)
.withServiceName("foo") .withServiceName("foo")
.start(); .start();
// between now and now + 100ms // Give a range of +/- 2 millis
assertThat(span.getStartTime()).isBetween(tick, tick + 100 * 1000L); assertThat(span.getStartTime()).isBetween(MILLISECONDS.toNanos(tick - 2), MILLISECONDS.toNanos(tick + 2));
} }
@ -143,7 +143,7 @@ public class DDSpanBuilderTest {
final long expectedParentId = spanId; final long expectedParentId = spanId;
DDSpanContext mockedContext = mock(DDSpanContext.class); DDSpanContext mockedContext = mock(DDSpanContext.class);
when(mockedContext.getSpanId()).thenReturn(spanId); when(mockedContext.getSpanId()).thenReturn(spanId);
when(mockedContext.getServiceName()).thenReturn("foo"); when(mockedContext.getServiceName()).thenReturn("foo");