diff --git a/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle b/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle
index b8deeab46c..d4ed32568a 100644
--- a/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle
+++ b/dd-java-agent/instrumentation/apache-httpclient-4.3/apache-httpclient-4.3.gradle
@@ -13,17 +13,25 @@ versionScan {
// "org.apache.http.HttpException" : null,
// "org.apache.http.HttpRequest" : null,
// "org.apache.http.client.RedirectStrategy" : null,
- "org.apache.http.client.methods.CloseableHttpResponse" : null,
- "org.apache.http.client.methods.HttpExecutionAware" : null,
- "org.apache.http.client.methods.HttpRequestWrapper" : null,
- "org.apache.http.client.protocol.HttpClientContext" : null,
+ "org.apache.http.client.methods.CloseableHttpResponse": null,
+ "org.apache.http.client.methods.HttpExecutionAware" : null,
+ "org.apache.http.client.methods.HttpRequestWrapper" : null,
+ "org.apache.http.client.protocol.HttpClientContext" : null,
// "org.apache.http.conn.routing.HttpRoute" : null,
- "org.apache.http.impl.execchain.ClientExecChain": null
+ "org.apache.http.impl.execchain.ClientExecChain" : null
]
}
apply from: "${rootDir}/gradle/java.gradle"
+apply plugin: 'org.unbroken-dome.test-sets'
+
+testSets {
+ latestDepTest {
+ dirName = 'test'
+ }
+}
+
dependencies {
compileOnly group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3'
@@ -33,4 +41,10 @@ dependencies {
compile deps.opentracing
annotationProcessor deps.autoservice
implementation deps.autoservice
+
+ testCompile project(':dd-java-agent:testing')
+ testCompile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3'
+
+
+ latestDepTestCompile group: 'org.apache.httpcomponents', name: 'httpclient', version: '+'
}
diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy b/dd-java-agent/instrumentation/apache-httpclient-4.3/src/test/groovy/ApacheHttpClientTest.groovy
similarity index 54%
rename from dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy
rename to dd-java-agent/instrumentation/apache-httpclient-4.3/src/test/groovy/ApacheHttpClientTest.groovy
index d378079ad8..791cbc39fe 100644
--- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy
+++ b/dd-java-agent/instrumentation/apache-httpclient-4.3/src/test/groovy/ApacheHttpClientTest.groovy
@@ -1,38 +1,49 @@
-package datadog.trace.agent.integration.httpclient
-
import datadog.opentracing.DDSpan
-import datadog.opentracing.DDTracer
-import datadog.trace.agent.integration.TestHttpServer
-import datadog.trace.agent.test.IntegrationTestUtils
+import datadog.trace.agent.test.AgentTestRunner
import datadog.trace.api.DDSpanTypes
-import datadog.trace.common.writer.ListWriter
+import io.opentracing.Scope
+import io.opentracing.SpanContext
+import io.opentracing.propagation.Format
+import io.opentracing.propagation.TextMap
import io.opentracing.tag.Tags
+import io.opentracing.util.GlobalTracer
import org.apache.http.HttpResponse
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.impl.client.HttpClientBuilder
import org.apache.http.message.BasicHeader
+import ratpack.handling.Context
import spock.lang.Shared
-import spock.lang.Specification
-class ApacheHttpClientTest extends Specification {
+import static datadog.trace.agent.test.TestUtils.runUnderTrace
+import static ratpack.groovy.test.embed.GroovyEmbeddedApp.ratpack
+
+class ApacheHttpClientTest extends AgentTestRunner {
@Shared
- def writer = new ListWriter()
- @Shared
- def tracer = new DDTracer(writer)
+ def server = ratpack {
+ handlers {
+ get {
+ String msg = "
Hello test.
\n"
+ boolean isDDServer = true
+ if (context.request.getHeaders().contains("is-dd-server")) {
+ isDDServer = Boolean.parseBoolean(context.request.getHeaders().get("is-dd-server"))
+ }
+ if (isDDServer) {
+ final SpanContext extractedContext =
+ GlobalTracer.get()
+ .extract(Format.Builtin.HTTP_HEADERS, new RatpackResponseAdapter(context))
+ Scope scope =
+ GlobalTracer.get()
+ .buildSpan("test-http-server")
+ .asChildOf(extractedContext)
+ .startActive(true)
+ scope.close()
+ }
- def setupSpec() {
- IntegrationTestUtils.registerOrReplaceGlobalTracer(tracer)
- TestHttpServer.startServer()
- }
-
- def cleanupSpec() {
- TestHttpServer.stopServer()
- }
-
- def setup() {
- writer.clear()
+ response.status(200).send(msg)
+ }
+ }
}
def "trace request with propagation"() {
@@ -40,10 +51,9 @@ class ApacheHttpClientTest extends Specification {
final HttpClientBuilder builder = HttpClientBuilder.create()
final HttpClient client = builder.build()
- IntegrationTestUtils.runUnderTrace("someTrace") {
+ runUnderTrace("someTrace") {
try {
- HttpResponse response =
- client.execute(new HttpGet(new URI("http://localhost:" + TestHttpServer.getPort())))
+ HttpResponse response = client.execute(new HttpGet(server.getAddress()))
assert response.getStatusLine().getStatusCode() == 200
} catch (Exception e) {
e.printStackTrace()
@@ -53,11 +63,11 @@ class ApacheHttpClientTest extends Specification {
expect:
// one trace on the server, one trace on the client
- writer.size() == 2
- final List serverTrace = writer.get(0)
+ TEST_WRITER.size() == 2
+ final List serverTrace = TEST_WRITER.get(0)
serverTrace.size() == 1
- final List clientTrace = writer.get(1)
+ final List clientTrace = TEST_WRITER.get(1)
clientTrace.size() == 3
clientTrace.get(0).getOperationName() == "someTrace"
// our instrumentation makes 2 spans for apache-httpclient
@@ -71,9 +81,9 @@ class ApacheHttpClientTest extends Specification {
clientSpan.getType() == DDSpanTypes.HTTP_CLIENT
clientSpan.getTags()[Tags.HTTP_METHOD.getKey()] == "GET"
clientSpan.getTags()[Tags.HTTP_STATUS.getKey()] == 200
- clientSpan.getTags()[Tags.HTTP_URL.getKey()] == "http://localhost:" + TestHttpServer.getPort()
+ clientSpan.getTags()[Tags.HTTP_URL.getKey()] == server.getAddress().toString()
clientSpan.getTags()[Tags.PEER_HOSTNAME.getKey()] == "localhost"
- clientSpan.getTags()[Tags.PEER_PORT.getKey()] == TestHttpServer.getPort()
+ clientSpan.getTags()[Tags.PEER_PORT.getKey()] == server.getAddress().port
clientSpan.getTags()[Tags.SPAN_KIND.getKey()] == Tags.SPAN_KIND_CLIENT
// client trace propagates to server
@@ -82,17 +92,15 @@ class ApacheHttpClientTest extends Specification {
clientSpan.getSpanId() == serverTrace.get(0).getParentId()
}
-
def "trace request without propagation"() {
setup:
final HttpClientBuilder builder = HttpClientBuilder.create()
final HttpClient client = builder.build()
- IntegrationTestUtils.runUnderTrace("someTrace") {
+ runUnderTrace("someTrace") {
try {
- HttpGet request = new HttpGet(new URI("http://localhost:"
- + TestHttpServer.getPort()))
- request.addHeader(new BasicHeader(TestHttpServer.IS_DD_SERVER, "false"))
+ HttpGet request = new HttpGet(server.getAddress())
+ request.addHeader(new BasicHeader("is-dd-server", "false"))
HttpResponse response = client.execute(request)
assert response.getStatusLine().getStatusCode() == 200
} catch (Exception e) {
@@ -102,8 +110,8 @@ class ApacheHttpClientTest extends Specification {
}
expect:
// only one trace (client).
- writer.size() == 1
- final List clientTrace = writer.get(0)
+ TEST_WRITER.size() == 1
+ final List clientTrace = TEST_WRITER.get(0)
clientTrace.size() == 3
clientTrace.get(0).getOperationName() == "someTrace"
// our instrumentation makes 2 spans for apache-httpclient
@@ -115,10 +123,27 @@ class ApacheHttpClientTest extends Specification {
clientSpan.getOperationName() == "http.request"
clientSpan.getTags()[Tags.HTTP_METHOD.getKey()] == "GET"
clientSpan.getTags()[Tags.HTTP_STATUS.getKey()] == 200
- clientSpan.getTags()[Tags.HTTP_URL.getKey()] == "http://localhost:" + TestHttpServer.getPort()
+ clientSpan.getTags()[Tags.HTTP_URL.getKey()] == server.getAddress().toString()
clientSpan.getTags()[Tags.PEER_HOSTNAME.getKey()] == "localhost"
- clientSpan.getTags()[Tags.PEER_PORT.getKey()] == TestHttpServer.getPort()
+ clientSpan.getTags()[Tags.PEER_PORT.getKey()] == server.getAddress().port
clientSpan.getTags()[Tags.SPAN_KIND.getKey()] == Tags.SPAN_KIND_CLIENT
}
+ private static class RatpackResponseAdapter implements TextMap {
+ final Context context
+
+ RatpackResponseAdapter(Context context) {
+ this.context = context
+ }
+
+ @Override
+ void put(String key, String value) {
+ context.response.set(key, value)
+ }
+
+ @Override
+ Iterator> iterator() {
+ return context.request.getHeaders().asMultiValueMap().entrySet().iterator()
+ }
+ }
}
diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java
index 6f77f1980c..06f0f4b19d 100644
--- a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java
+++ b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java
@@ -196,14 +196,19 @@ public class PendingTrace extends ConcurrentLinkedDeque {
void start() {
executorService.scheduleAtFixedRate(new SpanCleaner(), 0, CLEAN_FREQUENCY, TimeUnit.SECONDS);
- Runtime.getRuntime()
- .addShutdownHook(
- new Thread() {
- @Override
- public void run() {
- PendingTrace.SpanCleaner.this.close();
- }
- });
+ try {
+ Runtime.getRuntime()
+ .addShutdownHook(
+ new Thread() {
+ @Override
+ public void run() {
+ PendingTrace.SpanCleaner.this.close();
+ }
+ });
+ } catch (final IllegalStateException ex) {
+ // The JVM might be shutting down.
+ log.debug("Error adding shutdown hook.", ex);
+ }
}
@Override