Add tests for vertx HTTP server
MODIFY
dd-java-agent/instrumentation/netty-4.1/netty-4.1.gradle
dd-java-agent/instrumentation/netty-4.1/netty-4.1.gradle
@@ -40,7 +40,6 @@ dependencies {
testCompile project(':dd-java-agent:testing')
testCompile project(':dd-java-agent:instrumentation:java-concurrent')
-
testCompile group: 'io.netty', name: 'netty-codec-http', version: '4.1.0.Final'
testCompile group: 'org.asynchttpclient', name: 'async-http-client', version: '2.1.0'
}

ADD
dd-java-agent/instrumentation/vertx/src/test/groovy/VertxServerTest.groovy
+import datadog.trace.agent.test.AgentTestRunner
+import datadog.trace.agent.test.TestUtils
+import datadog.trace.agent.test.utils.OkHttpUtils
+import datadog.trace.api.DDSpanTypes
+import datadog.trace.api.DDTags
+import io.netty.handler.codec.http.HttpResponseStatus
+import io.opentracing.tag.Tags
+import io.vertx.core.Vertx
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import spock.lang.Shared
+
+class VertxServerTest extends AgentTestRunner {
+
+ @Shared
+ OkHttpClient client = OkHttpUtils.client()
+
+ @Shared
+ int port
+ @Shared
+ Vertx server
+
+ def setupSpec() {
+ port = TestUtils.randomOpenPort()
+ server = VertxWebTestServer.start(port)
+ }
+
+ def cleanupSpec() {
+ server.close()
+ }
+
+ def "test server request/response"() {
+ setup:
+ def request = new Request.Builder()
+ .url("http://localhost:$port/test")
+ .header("x-datadog-trace-id", "123")
+ .header("x-datadog-parent-id", "456")
+ .get()
+ .build()
+ def response = client.newCall(request).execute()
+
+ expect:
+ response.code() == 200
+ response.body().string() == "Hello World"
+
+ and:
+ assertTraces(1) {
+ trace(0, 2) {
+ span(0) {
+ traceId "123"
+ parentId "456"
+ serviceName "unnamed-java-app"
+ operationName "netty.request"
+ resourceName "GET /test"
+ spanType DDSpanTypes.HTTP_SERVER
+ errored false
+ tags {
+ "$Tags.COMPONENT.key" "netty"
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" 200
+ "$Tags.HTTP_URL.key" "http://localhost:$port/test"
+ "$Tags.PEER_HOSTNAME.key" "localhost"
+ "$Tags.PEER_PORT.key" Integer
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ defaultTags()
+ }
+ }
+ span(1) {
+ childOf span(0)
+ assert span(1).operationName.endsWith('.tracedMethod')
+ }
+ }
+ }
+ }
+
+ def "test #responseCode response handling"() {
+ setup:
+ def request = new Request.Builder().url("http://localhost:$port/$path").get().build()
+ def response = client.newCall(request).execute()
+
+ expect:
+ response.code() == responseCode.code()
+
+ and:
+ assertTraces(1) {
+ trace(0, 1) {
+ span(0) {
+ serviceName "unnamed-java-app"
+ operationName "netty.request"
+ resourceName name
+ spanType DDSpanTypes.HTTP_SERVER
+ errored error
+ tags {
+ "$Tags.COMPONENT.key" "netty"
+ "$Tags.HTTP_METHOD.key" "GET"
+ "$Tags.HTTP_STATUS.key" responseCode.code()
+ "$Tags.HTTP_URL.key" "http://localhost:$port/$path"
+ "$Tags.PEER_HOSTNAME.key" "localhost"
+ "$Tags.PEER_PORT.key" Integer
+ "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_SERVER
+ "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_SERVER
+ if (error) {
+ tag("error", true)
+ }
+ defaultTags()
+ }
+ }
+ }
+ }
+
+ where:
+ responseCode | name | path | error
+ HttpResponseStatus.OK | "GET /" | "" | false
+ HttpResponseStatus.NOT_FOUND | "404" | "doesnt-exit" | false
+ HttpResponseStatus.INTERNAL_SERVER_ERROR | "GET /error" | "error" | true
+ }
+}

ADD
dd-java-agent/instrumentation/vertx/src/test/java/VertxWebTestServer.java
+import datadog.trace.api.Trace;
+import io.vertx.core.AbstractVerticle;
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.ext.web.Router;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+public class VertxWebTestServer extends AbstractVerticle {
+
+ public static Vertx start(final int port) throws ExecutionException, InterruptedException {
+ /* This is highly against Vertx ideas, but our tests are synchronous
+ so we have to make sure server is up and running */
+ final CompletableFuture<Void> future = new CompletableFuture<>();
+
+ final Vertx vertx = Vertx.vertx(new VertxOptions());
+ vertx.deployVerticle(
+ new VertxWebTestServer(port),
+ res -> {
+ if (!res.succeeded()) {
+ throw new RuntimeException("Cannot deploy server Verticle");
+ }
+ future.complete(null);
+ });
+
+ future.get();
+
+ return vertx;
+ }
+
+ private final int port;
+
+ public VertxWebTestServer(final int port) {
+ this.port = port;
+ }
+
+ @Override
+ public void start() {
+ final Router router = Router.router(vertx);
+
+ router
+ .route("/")
+ .handler(
+ routingContext -> {
+ routingContext.response().putHeader("content-type", "text/html").end("Hello World");
+ });
+ router
+ .route("/error")
+ .handler(
+ routingContext -> {
+ routingContext.response().setStatusCode(500).end();
+ });
+ router
+ .route("/test")
+ .handler(
+ routingContext -> {
+ tracedMethod();
+ routingContext.next();
+ })
+ .blockingHandler(
+ routingContext -> {
+ routingContext.next();
+ })
+ .handler(
+ routingContext -> {
+ routingContext.response().putHeader("content-type", "text/html").end("Hello World");
+ });
+
+ vertx.createHttpServer().requestHandler(router::accept).listen(port);
+ }
+
+ @Trace
+ public void tracedMethod() {}
+}

ADD
dd-java-agent/instrumentation/vertx/vertx.gradle
+// Set properties before any plugins get loaded
+ext {
+ minJavaVersionForTests = JavaVersion.VERSION_1_8
+}
+
+apply from: "${rootDir}/gradle/java.gradle"
+
+muzzle {
+ pass {
+ group = "io.vertx"
+ module = "vertx-web"
+ versions = "[4.1.0.Final,)"
+ assertInverse = true
+ }
+ pass {
+ group = "io.netty"
+ module = "netty"
+ versions = "[4.1.0.Final,)"
+ assertInverse = true
+ }
+}
+
+apply plugin: 'org.unbroken-dome.test-sets'
+
+testSets {
+ latestDepTest {
+ dirName = 'test'
+ }
+}
+
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+dependencies {
+ compileOnly group: 'io.vertx', name: 'vertx-web', version: '3.5.0'
+
+ compile project(':dd-java-agent:agent-tooling')
+
+ compile deps.bytebuddy
+ compile deps.opentracing
+ annotationProcessor deps.autoservice
+ implementation deps.autoservice
+
+ testCompile project(':dd-java-agent:testing')
+ testCompile project(':dd-java-agent:instrumentation:java-concurrent')
+ testCompile project(':dd-java-agent:instrumentation:trace-annotation')
+ testCompile project(':dd-java-agent:instrumentation:netty-4.1')
+ testCompile group: 'io.vertx', name: 'vertx-web', version: '3.5.0'
+}

MODIFY
settings.gradle
settings.gradle
@@ -56,6 +56,7 @@ include ':dd-java-agent:instrumentation:spring-web'
include ':dd-java-agent:instrumentation:spring-webflux'
include ':dd-java-agent:instrumentation:spymemcached-2.12'
include ':dd-java-agent:instrumentation:trace-annotation'
+include ':dd-java-agent:instrumentation:vertx'
// benchmark
include ':dd-java-agent:benchmark'

Add tests for vertx HTTP server