From 0dd8a992985bccc2013ef77d2bf37796d2adc5ae Mon Sep 17 00:00:00 2001 From: datadog-bits <263423550+datadog-bits@users.noreply.github.com> Date: Wed, 28 Oct 2026 09:38:56 +0000 Subject: [PATCH 1/2] Fix Vert.x HTTP/2 body race DD_BEW2HQ Co-authored-by: cgcote <5115638+cgcote@users.noreply.github.com> --- ...ResponseEndHandlerInstrumentationTest.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java b/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java index 25201f3e872..5f3c684ce5c 100644 --- a/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java +++ b/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java @@ -7,10 +7,9 @@ import datadog.trace.agent.test.AbstractInstrumentationTest; import io.vertx.core.Handler; import io.vertx.core.Vertx; -import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.http.HttpClientResponse; +import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; @@ -23,6 +22,8 @@ import java.net.ServerSocket; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.util.AbstractMap.SimpleEntry; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterAll; @@ -113,17 +114,22 @@ void wrapsApplicationEndHandlerOnVertx51Http2Response() throws Exception { .setProtocolVersion(HttpVersion.HTTP_2) .setHttp2ClearTextUpgrade(false)); try { - HttpClientResponse response = + Map.Entry response = client .request(HttpMethod.GET, port, "localhost", "/end-handler-wrapper") - .compose(request -> request.send()) + .compose(HttpClientRequest::send) + // Subscribe on the event loop before response data can be discarded. + .compose( + resp -> + resp.body() + .map( + body -> + new SimpleEntry<>( + resp.statusCode(), body.toString(StandardCharsets.UTF_8)))) .toCompletionStage() .toCompletableFuture() .get(10, TimeUnit.SECONDS); - Buffer body = - response.body().toCompletionStage().toCompletableFuture().get(10, TimeUnit.SECONDS); - - assertWrapped(response.statusCode(), body.toString(StandardCharsets.UTF_8), HTTP2_RESPONSE); + assertWrapped(response.getKey(), response.getValue(), HTTP2_RESPONSE); } finally { client.close().toCompletionStage().toCompletableFuture().get(10, TimeUnit.SECONDS); } From bd7f4e053095611a2e4b34fc071df4de25ef20b9 Mon Sep 17 00:00:00 2001 From: datadog-bits <263423550+datadog-bits@users.noreply.github.com> Date: Thu, 29 Oct 2026 12:25:59 +0000 Subject: [PATCH 2/2] Extract Vert.x response collector DD_BEW2HQ Co-authored-by: cgcote <5115638+cgcote@users.noreply.github.com> --- ...ResponseEndHandlerInstrumentationTest.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java b/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java index 5f3c684ce5c..7dd284f456d 100644 --- a/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java +++ b/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-5.0/src/test/java/server/HttpServerResponseEndHandlerInstrumentationTest.java @@ -5,11 +5,12 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue; import datadog.trace.agent.test.AbstractInstrumentationTest; +import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.http.HttpClientRequest; +import io.vertx.core.http.HttpClientResponse; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; @@ -117,15 +118,8 @@ void wrapsApplicationEndHandlerOnVertx51Http2Response() throws Exception { Map.Entry response = client .request(HttpMethod.GET, port, "localhost", "/end-handler-wrapper") - .compose(HttpClientRequest::send) // Subscribe on the event loop before response data can be discarded. - .compose( - resp -> - resp.body() - .map( - body -> - new SimpleEntry<>( - resp.statusCode(), body.toString(StandardCharsets.UTF_8)))) + .compose(request -> request.send().compose(this::collectResponse)) .toCompletionStage() .toCompletableFuture() .get(10, TimeUnit.SECONDS); @@ -135,6 +129,14 @@ void wrapsApplicationEndHandlerOnVertx51Http2Response() throws Exception { } } + private Future> collectResponse(HttpClientResponse response) { + return response + .body() + .map( + body -> + new SimpleEntry<>(response.statusCode(), body.toString(StandardCharsets.UTF_8))); + } + private static boolean hasVertx51Http1Response() { return hasClass(HTTP1_RESPONSE); }