diff --git a/README.md b/README.md index 99d6bf0d5dd..26bddc4add3 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,8 @@ gather all traces in your [Datadog](https://app.datadoghq.com) account. * [Introduction to the Datadog APM](https://www.datadoghq.com/apm/). Learn what you can do with the Next-Gen APM and how to get started. * [Install the Datadog Java agent](dd-java-agent). Instructions for supported technologies, web-servers and frameworks. * [Browse examples](dd-trace-examples). See how to instrument legacy projects based on the most used tehcnologies. -* [DD Trace API](dd-trace). We choose to embrace the Opentracting initiative. So feel free to use the Trace Java API to customize your instrumentation. +* [Instrument with OpenTracing](https://github.com/opentracing/opentracing-java). Datadog embraces the OpenTracing initiative. So feel free to use the Trace Java API to customize your instrumentation. +* [DD Trace](dd-trace). This Java implementation of the opentracing api is used to report traces to Datadog. ### Help or questions? diff --git a/dd-trace/pom.xml b/dd-trace/pom.xml index 723553ce334..4c67f100c94 100644 --- a/dd-trace/pom.xml +++ b/dd-trace/pom.xml @@ -88,6 +88,24 @@ 2.7.22 test + + org.spockframework + spock-core + 1.0-groovy-2.4 + test + + + org.codehaus.groovy + groovy-all + 2.4.4 + test + + + io.ratpack + ratpack-groovy-test + 1.4.6 + test + diff --git a/dd-trace/src/test/groovy/com/datadog/trace/SpanFactory.groovy b/dd-trace/src/test/groovy/com/datadog/trace/SpanFactory.groovy new file mode 100644 index 00000000000..67b7a1c8b7e --- /dev/null +++ b/dd-trace/src/test/groovy/com/datadog/trace/SpanFactory.groovy @@ -0,0 +1,23 @@ +package com.datadog.trace + +import com.datadoghq.trace.DDSpan +import com.datadoghq.trace.DDSpanContext + +class SpanFactory { + static def newSpanOf(long timestampMicro) { + def context = new DDSpanContext( + 1L, + 1L, + 0L, + "fakeService", + "fakeOperation", + "fakeResource", + Collections.emptyMap(), + false, + "fakeType", + Collections.emptyMap(), + null, + null); + return new DDSpan(timestampMicro, context) + } +} diff --git a/dd-trace/src/test/groovy/com/datadoghq/trace/writer/DDApiTest.groovy b/dd-trace/src/test/groovy/com/datadoghq/trace/writer/DDApiTest.groovy new file mode 100644 index 00000000000..2af05eb56c7 --- /dev/null +++ b/dd-trace/src/test/groovy/com/datadoghq/trace/writer/DDApiTest.groovy @@ -0,0 +1,117 @@ +package com.datadoghq.trace.writer + +import com.datadog.trace.SpanFactory +import com.datadoghq.trace.DDSpan +import com.fasterxml.jackson.databind.ObjectMapper +import ratpack.http.MediaType +import spock.lang.AutoCleanup +import spock.lang.Specification + +import java.util.concurrent.atomic.AtomicReference + +import static ratpack.groovy.test.embed.GroovyEmbeddedApp.ratpack +import static ratpack.http.MediaType.APPLICATION_JSON + +class DDApiTest extends Specification { + static def mapper = new ObjectMapper() + + def "sending an empty list of traces returns no errors"() { + setup: + def agent = ratpack { + handlers { + put("v0.3/traces") { + response.status(200).send() + } + } + } + def client = new DDApi("localhost", agent.address.port) + + expect: + client.sendTraces([]) + + cleanup: + agent.close() + } + + def "non-200 response results in false returned"() { + setup: + def agent = ratpack { + handlers { + put("v0.3/traces") { + response.status(404).send() + } + } + } + def client = new DDApi("localhost", agent.address.port) + + expect: + !client.sendTraces([]) + + cleanup: + agent.close() + } + + def "content is sent as JSON"() { + setup: + def requestContentType = new AtomicReference() + def requestBody = new AtomicReference() + def agent = ratpack { + handlers { + put("v0.3/traces") { + requestContentType.set(request.contentType) + request.body.then { + requestBody.set(it.text) + response.send() + } + } + } + } + def client = new DDApi("localhost", agent.address.port) + + expect: + client.sendTraces(traces) + requestContentType.get().type == APPLICATION_JSON + areEqual(requestBody.get(), expectedRequestBody) + + cleanup: + agent.close() + + where: + traces | expectedRequestBody + [] | '[]' + [SpanFactory.newSpanOf(1L)] | '''[{ + "duration":0, + "error":0, + "meta":{"thread-name":"main","thread-id":"1"}, + "name":"fakeOperation", + "parent_id":0, + "resource":"fakeResource" + "service":"fakeService", + "span_id":1, + "start":1000, + "trace_id":1, + "type":"fakeType", + }]''' + [SpanFactory.newSpanOf(100L)] | '''[{ + "duration":0, + "error":0, + "meta":{"thread-name":"main","thread-id":"1"}, + "name":"fakeOperation", + "parent_id":0, + "resource":"fakeResource" + "service":"fakeService", + "span_id":1, + "start":100000, + "trace_id":1, + "type":"fakeType", + }]''' + } + + + static void areEqual(String json1, String json2) { + def tree1 = mapper.readTree json1 + def tree2 = mapper.readTree json2 + + assert tree1.equals(tree2) + } +}