From 739f2d0daa891b454300d85915fa1cc2ab8bda39 Mon Sep 17 00:00:00 2001 From: Nikolay Martynov Date: Mon, 15 Oct 2018 17:25:36 -0400 Subject: [PATCH] Add tests for vertx HTTP server --- .../netty-4.1/netty-4.1.gradle | 1 - .../src/test/groovy/VertxServerTest.groovy | 118 ++++++++++++++++++ .../src/test/java/VertxWebTestServer.java | 74 +++++++++++ .../instrumentation/vertx/vertx.gradle | 49 ++++++++ settings.gradle | 1 + 5 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 dd-java-agent/instrumentation/vertx/src/test/groovy/VertxServerTest.groovy create mode 100644 dd-java-agent/instrumentation/vertx/src/test/java/VertxWebTestServer.java create mode 100644 dd-java-agent/instrumentation/vertx/vertx.gradle diff --git a/dd-java-agent/instrumentation/netty-4.1/netty-4.1.gradle b/dd-java-agent/instrumentation/netty-4.1/netty-4.1.gradle index 6666b4a982..d7dcaaccf8 100644 --- a/dd-java-agent/instrumentation/netty-4.1/netty-4.1.gradle +++ b/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' } diff --git a/dd-java-agent/instrumentation/vertx/src/test/groovy/VertxServerTest.groovy b/dd-java-agent/instrumentation/vertx/src/test/groovy/VertxServerTest.groovy new file mode 100644 index 0000000000..14a52df75e --- /dev/null +++ b/dd-java-agent/instrumentation/vertx/src/test/groovy/VertxServerTest.groovy @@ -0,0 +1,118 @@ +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 + } +} diff --git a/dd-java-agent/instrumentation/vertx/src/test/java/VertxWebTestServer.java b/dd-java-agent/instrumentation/vertx/src/test/java/VertxWebTestServer.java new file mode 100644 index 0000000000..35efd021e2 --- /dev/null +++ b/dd-java-agent/instrumentation/vertx/src/test/java/VertxWebTestServer.java @@ -0,0 +1,74 @@ +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 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() {} +} diff --git a/dd-java-agent/instrumentation/vertx/vertx.gradle b/dd-java-agent/instrumentation/vertx/vertx.gradle new file mode 100644 index 0000000000..d842124209 --- /dev/null +++ b/dd-java-agent/instrumentation/vertx/vertx.gradle @@ -0,0 +1,49 @@ +// 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' +} diff --git a/settings.gradle b/settings.gradle index 516e15ce86..aeebb0a529 100644 --- a/settings.gradle +++ b/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'