diff --git a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsAsyncClientBodyInstrumentationTest.java b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsAsyncClientBodyInstrumentationTest.java new file mode 100644 index 000000000..b0e6ba494 --- /dev/null +++ b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsAsyncClientBodyInstrumentationTest.java @@ -0,0 +1,112 @@ +/* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.opentelemetry.javaagent.instrumentation.hypertrace.jaxrs.v2_0; + +import java.io.IOException; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyWriter; +import org.hypertrace.agent.testing.AbstractHttpClientTest; + +public class JaxrsAsyncClientBodyInstrumentationTest extends AbstractHttpClientTest { + + public JaxrsAsyncClientBodyInstrumentationTest() { + super(true); + } + + @Override + public Response doPostRequest( + String uri, Map headers, String body, String contentType) + throws ExecutionException, InterruptedException { + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + Client client = clientBuilder.register(MyDtoMessageBodyWriter.class).build(); + + Invocation.Builder builder = client.target(uri).request(); + + for (Map.Entry entry : headers.entrySet()) { + builder = builder.header(entry.getKey(), entry.getValue()); + } + + MyDto myDto = new MyDto(); + myDto.data = body; + + Future post = + builder.async().post(Entity.entity(myDto, MediaType.valueOf(contentType))); + javax.ws.rs.core.Response response = post.get(); + + return new Response(response.readEntity(String.class), response.getStatus()); + } + + @Override + public Response doGetRequest(String uri, Map headers) + throws ExecutionException, InterruptedException { + ClientBuilder clientBuilder = ClientBuilder.newBuilder(); + Client client = clientBuilder.build(); + + Invocation.Builder builder = client.target(uri).request(); + + for (Map.Entry entry : headers.entrySet()) { + builder = builder.header(entry.getKey(), entry.getValue()); + } + + Future responseFuture = builder.async().get(); + + javax.ws.rs.core.Response response = responseFuture.get(); + + String responseBody = response.readEntity(String.class); + + return new Response( + responseBody == null || responseBody.isEmpty() ? null : responseBody, response.getStatus()); + } + + public static class MyDto { + public String data; + } + + public static class MyDtoMessageBodyWriter implements MessageBodyWriter { + + @Override + public void writeTo( + MyDto myDto, + Class type, + Type genericType, + Annotation[] annotations, + MediaType mediaType, + MultivaluedMap httpHeaders, + OutputStream entityStream) + throws IOException, WebApplicationException { + entityStream.write((myDto.data).getBytes()); + } + + @Override + public boolean isWriteable( + Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return true; + } + } +} diff --git a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java index de828e5d5..e4975ba42 100644 --- a/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java +++ b/instrumentation/jaxrs-client-2.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/jaxrs/v2_0/JaxrsClientBodyInstrumentationTest.java @@ -16,240 +16,52 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.jaxrs.v2_0; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.sdk.trace.data.SpanData; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeoutException; -import javax.ws.rs.WebApplicationException; +import java.util.Map; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; -import javax.ws.rs.client.WebTarget; +import javax.ws.rs.client.Invocation; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedHashMap; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.ext.MessageBodyWriter; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class JaxrsClientBodyInstrumentationTest extends AbstractInstrumenterTest { - - private static final String JSON = "{\"id\":1,\"name\":\"John\"}"; - private static final TestHttpServer testHttpServer = new TestHttpServer(); - - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); - } +import org.hypertrace.agent.testing.AbstractHttpClientTest; - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); - } +public class JaxrsClientBodyInstrumentationTest extends AbstractHttpClientTest { - @Test - public void getJson() throws TimeoutException, InterruptedException { - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); - Client client = clientBuilder.build(); - - Response response = - client - .target(String.format("http://localhost:%d/get_json", testHttpServer.port())) - .request() - .header("test-request-header", "test-header-value") - .get(); - assertGetJson(response); - } + private static final Client client = ClientBuilder.newBuilder().build(); - @Test - public void getJsonAsync() throws TimeoutException, InterruptedException, ExecutionException { - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); - Client client = clientBuilder.build(); - - Future responseFuture = - client - .target(String.format("http://localhost:%d/get_json", testHttpServer.port())) - .request() - .header("test-request-header", "test-header-value") - .async() - .get(); - - Response response = responseFuture.get(); - assertGetJson(response); + public JaxrsClientBodyInstrumentationTest() { + super(true); } - public void assertGetJson(Response response) throws TimeoutException, InterruptedException { - Assertions.assertEquals(200, response.getStatus()); - // read entity has to happen before response.close() - String entity = response.readEntity(String.class); - Assertions.assertEquals(GetJsonHandler.RESPONSE_BODY, entity); - Assertions.assertEquals(false, Span.current().isRecording()); - response.close(); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(2, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - "test-header-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader("test-request-header"))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - SpanData responseBodySpan = traces.get(0).get(1); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - responseBodySpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } + @Override + public AbstractHttpClientTest.Response doPostRequest( + String uri, Map headers, String body, String contentType) { - @Test - public void postJson() throws TimeoutException, InterruptedException { - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); - Client client = clientBuilder.build(); - - MyDto myDto = new MyDto(); - myDto.name = "foo"; - - Response response = - client - .target(String.format("http://localhost:%d/post", testHttpServer.port())) - .request() - .header("test-request-header", "test-header-value") - .post(Entity.entity(JSON, MediaType.APPLICATION_JSON_TYPE)); - Assertions.assertEquals(204, response.getStatus()); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - JSON, clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } + Invocation.Builder builder = client.target(uri).request(); - @Test - public void postJsonDtoAsync() throws TimeoutException, InterruptedException, ExecutionException { - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); - Client client = clientBuilder.register(MyDtoMessageBodyWriter.class).build(); - - MyDto myDto = new MyDto(); - myDto.name = "name"; - - Future post = - client - .target(String.format("http://localhost:%d/post", testHttpServer.port())) - .request() - .header("test-request-header", "test-header-value") - .async() - .post(Entity.json(myDto)); - Response response = post.get(); - Assertions.assertEquals(204, response.getStatus()); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - myDto.getJson(), - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } + for (Map.Entry entry : headers.entrySet()) { + builder = builder.header(entry.getKey(), entry.getValue()); + } + + javax.ws.rs.core.Response response = + builder.post(Entity.entity(body, MediaType.valueOf(contentType))); - @Test - public void postUrlEncoded() throws TimeoutException, InterruptedException { - ClientBuilder clientBuilder = ClientBuilder.newBuilder(); - Client client = clientBuilder.build(); - - WebTarget webTarget = - client.target(String.format("http://localhost:%d/post", testHttpServer.port())); - MultivaluedMap formData = new MultivaluedHashMap<>(); - formData.add("key1", "value1"); - formData.add("key2", "value2"); - Response response = webTarget.request().post(Entity.form(formData)); - Assertions.assertEquals(204, response.getStatus()); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - "key1=value1&key2=value2", - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + return new Response(response.readEntity(String.class), response.getStatus()); } - public static class MyDto { - public String name; + @Override + public AbstractHttpClientTest.Response doGetRequest(String uri, Map headers) { + + Invocation.Builder builder = client.target(uri).request(); - public String getJson() { - return "{name:\"" + name + "\"}"; + for (Map.Entry entry : headers.entrySet()) { + builder = builder.header(entry.getKey(), entry.getValue()); } - } - public static class MyDtoMessageBodyWriter implements MessageBodyWriter { + javax.ws.rs.core.Response response = builder.get(); - @Override - public boolean isWriteable( - Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; - } + String responseBody = response.readEntity(String.class); - @Override - public void writeTo( - MyDto myDto, - Class type, - Type genericType, - Annotation[] annotations, - MediaType mediaType, - MultivaluedMap httpHeaders, - OutputStream entityStream) - throws IOException, WebApplicationException { - entityStream.write((myDto.getJson()).getBytes()); - } + return new Response( + responseBody == null || responseBody.isEmpty() ? null : responseBody, response.getStatus()); } } diff --git a/instrumentation/netty/netty-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/Netty40ClientInstrumentationTest.java b/instrumentation/netty/netty-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/Netty40ClientInstrumentationTest.java index 681a87e5f..5d7badda9 100644 --- a/instrumentation/netty/netty-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/Netty40ClientInstrumentationTest.java +++ b/instrumentation/netty/netty-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_0/client/Netty40ClientInstrumentationTest.java @@ -16,131 +16,77 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_0.client; -import io.opentelemetry.sdk.trace.data.SpanData; import java.io.ByteArrayInputStream; -import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; import org.asynchttpclient.AsyncCompletionHandler; import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.BoundRequestBuilder; import org.asynchttpclient.DefaultAsyncHttpClientConfig; import org.asynchttpclient.Dsl; import org.asynchttpclient.ListenableFuture; -import org.asynchttpclient.Response; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.hypertrace.agent.testing.AbstractHttpClientTest; -public class Netty40ClientInstrumentationTest extends AbstractInstrumenterTest { - - private static final String REQUEST_BODY = "hello_foo_bar"; - private static final String REQUEST_HEADER_NAME = "reqheadername"; - private static final String REQUEST_HEADER_VALUE = "reqheadervalue"; - - private static final TestHttpServer testHttpServer = new TestHttpServer(); +public class Netty40ClientInstrumentationTest extends AbstractHttpClientTest { private final DefaultAsyncHttpClientConfig clientConfig = new DefaultAsyncHttpClientConfig.Builder().setRequestTimeout(30000).build(); private final AsyncHttpClient asyncHttpClient = Dsl.asyncHttpClient(clientConfig); - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); + public Netty40ClientInstrumentationTest() { + super(false); } - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); - } + @Override + public Response doPostRequest( + String uri, Map headers, String body, String contentType) + throws ExecutionException, InterruptedException { - @Test - public void getJson() throws ExecutionException, InterruptedException, TimeoutException { - ListenableFuture response = - asyncHttpClient - .prepareGet(String.format("http://localhost:%d/get_json", testHttpServer.port())) - .addHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .execute( - new AsyncCompletionHandler() { - @Override - public Object onCompleted(Response response) throws Exception { - return null; - } - }); + ByteArrayInputStream inputStream = new ByteArrayInputStream(body.getBytes()); + BoundRequestBuilder requestBuilder = asyncHttpClient.preparePost(uri).setBody(inputStream); - // wait for the result - response.get(); + for (Map.Entry entry : headers.entrySet()) { + requestBuilder = requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + + requestBuilder = requestBuilder.addHeader("Content-Type", contentType); + ListenableFuture response = + requestBuilder.execute( + new AsyncCompletionHandler() { + @Override + public Response onCompleted(org.asynchttpclient.Response response) { + return new Response( + response.hasResponseBody() ? response.getResponseBody() : null, + response.getStatusCode()); + } + }); - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + // wait for the result + return response.get(); } - @Test - public void post() throws ExecutionException, InterruptedException, TimeoutException { - ByteArrayInputStream inputStream = new ByteArrayInputStream(REQUEST_BODY.getBytes()); + @Override + public Response doGetRequest(String uri, Map headers) + throws ExecutionException, InterruptedException { - ListenableFuture response = - asyncHttpClient - .preparePost(String.format("http://localhost:%d/post", testHttpServer.port())) - .setBody(inputStream) - .addHeader("Content-Type", "application/json") - .addHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .execute( - new AsyncCompletionHandler() { - @Override - public Object onCompleted(Response response) throws Exception { - return null; - } - }); + BoundRequestBuilder requestBuilder = asyncHttpClient.prepareGet(uri); - // wait for the result - response.get(); + for (Map.Entry entry : headers.entrySet()) { + requestBuilder = requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertEquals( - REQUEST_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + ListenableFuture response = + requestBuilder.execute( + new AsyncCompletionHandler() { + @Override + public Response onCompleted(org.asynchttpclient.Response response) { + return new Response( + response.hasResponseBody() ? response.getResponseBody() : null, + response.getStatusCode()); + } + }); + + // wait for the result + return response.get(); } } diff --git a/instrumentation/netty/netty-4.1/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/Netty41ClientInstrumentationTest.java b/instrumentation/netty/netty-4.1/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/Netty41ClientInstrumentationTest.java index 60e602e9f..dd3b073dd 100644 --- a/instrumentation/netty/netty-4.1/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/Netty41ClientInstrumentationTest.java +++ b/instrumentation/netty/netty-4.1/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/netty/v4_1/client/Netty41ClientInstrumentationTest.java @@ -16,131 +16,77 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.netty.v4_1.client; -import io.opentelemetry.sdk.trace.data.SpanData; import java.io.ByteArrayInputStream; -import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; import org.asynchttpclient.AsyncCompletionHandler; import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.BoundRequestBuilder; import org.asynchttpclient.DefaultAsyncHttpClientConfig; import org.asynchttpclient.Dsl; import org.asynchttpclient.ListenableFuture; -import org.asynchttpclient.Response; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.hypertrace.agent.testing.AbstractHttpClientTest; -public class Netty41ClientInstrumentationTest extends AbstractInstrumenterTest { - - private static final String REQUEST_BODY = "hello_foo_bar"; - private static final String REQUEST_HEADER_NAME = "reqheadername"; - private static final String REQUEST_HEADER_VALUE = "reqheadervalue"; - - private static final TestHttpServer testHttpServer = new TestHttpServer(); +public class Netty41ClientInstrumentationTest extends AbstractHttpClientTest { private final DefaultAsyncHttpClientConfig clientConfig = new DefaultAsyncHttpClientConfig.Builder().setRequestTimeout(30000).build(); private final AsyncHttpClient asyncHttpClient = Dsl.asyncHttpClient(clientConfig); - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); + public Netty41ClientInstrumentationTest() { + super(false); } - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); - } + @Override + public Response doPostRequest( + String uri, Map headers, String body, String contentType) + throws ExecutionException, InterruptedException { - @Test - public void getJson() throws ExecutionException, InterruptedException, TimeoutException { - ListenableFuture response = - asyncHttpClient - .prepareGet(String.format("http://localhost:%d/get_json", testHttpServer.port())) - .addHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .execute( - new AsyncCompletionHandler() { - @Override - public Object onCompleted(Response response) throws Exception { - return null; - } - }); + ByteArrayInputStream inputStream = new ByteArrayInputStream(body.getBytes()); + BoundRequestBuilder requestBuilder = asyncHttpClient.preparePost(uri).setBody(inputStream); - // wait for the result - response.get(); + for (Map.Entry entry : headers.entrySet()) { + requestBuilder = requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } + + requestBuilder = requestBuilder.addHeader("Content-Type", contentType); + ListenableFuture response = + requestBuilder.execute( + new AsyncCompletionHandler() { + @Override + public Response onCompleted(org.asynchttpclient.Response response) { + return new Response( + response.hasResponseBody() ? response.getResponseBody() : null, + response.getStatusCode()); + } + }); - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + // wait for the result + return response.get(); } - @Test - public void post() throws ExecutionException, InterruptedException, TimeoutException { - ByteArrayInputStream inputStream = new ByteArrayInputStream(REQUEST_BODY.getBytes()); + @Override + public Response doGetRequest(String uri, Map headers) + throws ExecutionException, InterruptedException { - ListenableFuture response = - asyncHttpClient - .preparePost(String.format("http://localhost:%d/post", testHttpServer.port())) - .setBody(inputStream) - .addHeader("Content-Type", "application/json") - .addHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .execute( - new AsyncCompletionHandler() { - @Override - public Object onCompleted(Response response) throws Exception { - return null; - } - }); + BoundRequestBuilder requestBuilder = asyncHttpClient.prepareGet(uri); - // wait for the result - response.get(); + for (Map.Entry entry : headers.entrySet()) { + requestBuilder = requestBuilder.addHeader(entry.getKey(), entry.getValue()); + } - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertEquals( - REQUEST_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + ListenableFuture response = + requestBuilder.execute( + new AsyncCompletionHandler() { + @Override + public Response onCompleted(org.asynchttpclient.Response response) { + return new Response( + response.hasResponseBody() ? response.getResponseBody() : null, + response.getStatusCode()); + } + }); + + // wait for the result + return response.get(); } } diff --git a/instrumentation/spring/spring-webflux-5.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/spring/webflux/SpringWebfluxClientTest.java b/instrumentation/spring/spring-webflux-5.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/spring/webflux/SpringWebfluxClientTest.java index bec242128..6a9c6bce9 100644 --- a/instrumentation/spring/spring-webflux-5.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/spring/webflux/SpringWebfluxClientTest.java +++ b/instrumentation/spring/spring-webflux-5.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/spring/webflux/SpringWebfluxClientTest.java @@ -16,106 +16,50 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.spring.webflux; -import io.opentelemetry.sdk.trace.data.SpanData; -import java.util.List; -import java.util.concurrent.TimeoutException; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Map; +import org.hypertrace.agent.testing.AbstractHttpClientTest; +import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec; import reactor.core.publisher.Mono; -public class SpringWebfluxClientTest extends AbstractInstrumenterTest { - - private static final String REQUEST_BODY = "hello_foo_bar"; - private static final String REQUEST_HEADER_NAME = "reqheadername"; - private static final String REQUEST_HEADER_VALUE = "reqheadervalue"; - - private static final TestHttpServer testHttpServer = new TestHttpServer(); - - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); - } +public class SpringWebfluxClientTest extends AbstractHttpClientTest { - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); + public SpringWebfluxClientTest() { + super(false); } - @Test - public void getJson() throws InterruptedException, TimeoutException { - WebClient client = - WebClient.builder() - .baseUrl(String.format("http://localhost:%d/get_json", testHttpServer.port())) - .defaultHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .build(); - RequestHeadersUriSpec requestHeadersUriSpec = client.get(); - Mono stringMono = requestHeadersUriSpec.retrieve().bodyToMono(String.class); - String responseBody = stringMono.block(); - Assertions.assertEquals(GetJsonHandler.RESPONSE_BODY, responseBody); + @Override + public Response doPostRequest( + String uri, Map headers, String body, String contentType) { + WebClient.Builder clientBuilder = WebClient.builder().baseUrl(uri); + for (Map.Entry entry : headers.entrySet()) { + clientBuilder = clientBuilder.defaultHeader(entry.getKey(), entry.getValue()); + } + clientBuilder = clientBuilder.defaultHeader("Content-Type", contentType); + WebClient client = clientBuilder.build(); - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + ClientResponse clientResponse = + client.post().body(Mono.just(body), String.class).exchange().block(); + if (clientResponse == null) fail(); + int responseStatus = clientResponse.statusCode().value(); + String responseBody = clientResponse.bodyToMono(String.class).block(); + return new Response(responseBody, responseStatus); } - @Test - public void post() throws InterruptedException, TimeoutException { - WebClient client = - WebClient.builder() - .baseUrl(String.format("http://localhost:%d/post", testHttpServer.port())) - .defaultHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .defaultHeader("Content-Type", "application/json") - .build(); - client.post().body(Mono.just(REQUEST_BODY), String.class).exchange().block(); + @Override + public Response doGetRequest(String uri, Map headers) { + WebClient.Builder clientBuilder = WebClient.builder().baseUrl(uri); + for (Map.Entry entry : headers.entrySet()) { + clientBuilder = clientBuilder.defaultHeader(entry.getKey(), entry.getValue()); + } + WebClient client = clientBuilder.build(); - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertEquals( - REQUEST_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + ClientResponse clientResponse = client.get().exchange().block(); + if (clientResponse == null) fail(); + int responseStatus = clientResponse.statusCode().value(); + String responseBody = clientResponse.bodyToMono(String.class).block(); + return new Response(responseBody, responseStatus); } } diff --git a/instrumentation/vertx-web-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/VertxClientInstrumentationTest.java b/instrumentation/vertx-web-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/VertxClientInstrumentationTest.java index 4663557bd..8aae96229 100644 --- a/instrumentation/vertx-web-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/VertxClientInstrumentationTest.java +++ b/instrumentation/vertx-web-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/vertx/VertxClientInstrumentationTest.java @@ -16,128 +16,102 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.vertx; -import io.opentelemetry.sdk.trace.data.SpanData; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; +import io.vertx.core.buffer.Buffer; 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 java.util.List; +import java.util.Map; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeoutException; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.hypertrace.agent.testing.AbstractHttpClientTest; -public class VertxClientInstrumentationTest extends AbstractInstrumenterTest { - - private static final String REQUEST_BODY = "hello_foo_bar"; - private static final String REQUEST_HEADER_NAME = "reqheadername"; - private static final String REQUEST_HEADER_VALUE = "reqheadervalue"; - - private static final TestHttpServer testHttpServer = new TestHttpServer(); +public class VertxClientInstrumentationTest extends AbstractHttpClientTest { private static final Vertx vertx = Vertx.vertx(new VertxOptions()); private final HttpClientOptions clientOptions = new HttpClientOptions(); private final HttpClient httpClient = vertx.createHttpClient(clientOptions); - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); + public VertxClientInstrumentationTest() { + super(false); } - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); + @Override + public Response doPostRequest( + String uri, Map headers, String body, String contentType) + throws InterruptedException { + CountDownLatch countDownLatch = new CountDownLatch(1); + + HttpClientRequest request = httpClient.requestAbs(HttpMethod.POST, uri); + + for (Map.Entry entry : headers.entrySet()) { + request = request.putHeader(entry.getKey(), entry.getValue()); + } + request = request.putHeader("Content-Type", contentType); + BufferHandler bufferHandler = new BufferHandler(countDownLatch); + ResponseHandler responseHandler = new ResponseHandler(bufferHandler); + + request.handler(responseHandler).end(body); + + countDownLatch.await(); + return new Response(bufferHandler.responseBody, responseHandler.responseStatus); } - @Test - public void getJson() throws InterruptedException, TimeoutException { + @Override + public Response doGetRequest(String uri, Map headers) + throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(1); - httpClient - .request(HttpMethod.GET, testHttpServer.port(), "localhost", "/get_json") - .putHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .handler( - new Handler() { - @Override - public void handle(HttpClientResponse response) { - Assertions.assertEquals(200, response.statusCode()); - countDownLatch.countDown(); - } - }) - .end(); + + HttpClientRequest request = httpClient.requestAbs(HttpMethod.GET, uri); + + for (Map.Entry entry : headers.entrySet()) { + request = request.putHeader(entry.getKey(), entry.getValue()); + } + BufferHandler bufferHandler = new BufferHandler(countDownLatch); + ResponseHandler responseHandler = new ResponseHandler(bufferHandler); + + request.handler(responseHandler).end(); + countDownLatch.await(); + return new Response( + bufferHandler.responseBody == null || bufferHandler.responseBody.isEmpty() + ? null + : bufferHandler.responseBody, + responseHandler.responseStatus); + } + + static class ResponseHandler implements Handler { + + int responseStatus; + final BufferHandler bufferHandler; - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + ResponseHandler(BufferHandler bufferHandler) { + this.bufferHandler = bufferHandler; + } + + @Override + public void handle(HttpClientResponse response) { + response.bodyHandler(bufferHandler); + responseStatus = response.statusCode(); + } } - @Test - public void post() throws InterruptedException, TimeoutException { - CountDownLatch countDownLatch = new CountDownLatch(1); - httpClient - .request(HttpMethod.POST, testHttpServer.port(), "localhost", "/post") - .putHeader(REQUEST_HEADER_NAME, REQUEST_HEADER_VALUE) - .putHeader("Content-Type", "application/json") - .handler( - new Handler() { - @Override - public void handle(HttpClientResponse response) { - Assertions.assertEquals(204, response.statusCode()); - countDownLatch.countDown(); - } - }) - .end(REQUEST_BODY); - countDownLatch.await(); + static class BufferHandler implements Handler { + + String responseBody; + final CountDownLatch countDownLatch; + + BufferHandler(CountDownLatch countDownLatch) { + this.countDownLatch = countDownLatch; + } - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - REQUEST_HEADER_VALUE, - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader(REQUEST_HEADER_NAME))); - Assertions.assertEquals( - TestHttpServer.RESPONSE_HEADER_VALUE, - clientSpan - .getAttributes() - .get( - HypertraceSemanticAttributes.httpResponseHeader( - TestHttpServer.RESPONSE_HEADER_NAME))); - Assertions.assertEquals( - REQUEST_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + @Override + public void handle(Buffer responseBodyBuffer) { + responseBody = responseBodyBuffer.getString(0, responseBodyBuffer.length()); + countDownLatch.countDown(); + } } } diff --git a/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributes.java b/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributes.java index 59a63b315..5e94c8cd7 100644 --- a/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributes.java +++ b/javaagent-core/src/main/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributes.java @@ -30,11 +30,11 @@ private HypertraceSemanticAttributes() {} public static final String ADDITIONAL_DATA_SPAN_NAME = "additional-data"; public static AttributeKey httpRequestHeader(String header) { - return AttributeKey.stringKey("http.request.header." + header); + return AttributeKey.stringKey("http.request.header." + header.toLowerCase()); } public static AttributeKey httpResponseHeader(String header) { - return AttributeKey.stringKey("http.response.header." + header); + return AttributeKey.stringKey("http.response.header." + header.toLowerCase()); } public static final AttributeKey HTTP_REQUEST_BODY = @@ -51,10 +51,10 @@ public static AttributeKey httpResponseHeader(String header) { AttributeKey.stringKey("rpc.response.body"); public static final AttributeKey rpcRequestMetadata(String key) { - return AttributeKey.stringKey("rpc.request.metadata." + key); + return AttributeKey.stringKey("rpc.request.metadata." + key.toLowerCase()); } public static final AttributeKey rpcResponseMetadata(String key) { - return AttributeKey.stringKey("rpc.response.metadata." + key); + return AttributeKey.stringKey("rpc.response.metadata." + key.toLowerCase()); } } diff --git a/javaagent-core/src/test/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributesTest.java b/javaagent-core/src/test/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributesTest.java new file mode 100644 index 000000000..b69161f44 --- /dev/null +++ b/javaagent-core/src/test/java/org/hypertrace/agent/core/instrumentation/HypertraceSemanticAttributesTest.java @@ -0,0 +1,50 @@ +/* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hypertrace.agent.core.instrumentation; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class HypertraceSemanticAttributesTest { + + @Test + public void caseInsensitiveHttpRequestHeader() { + Assertions.assertEquals( + "http.request.header.content-type", + HypertraceSemanticAttributes.httpRequestHeader("Content-Type").getKey()); + } + + @Test + public void caseInsensitiveHttpResponseHeader() { + Assertions.assertEquals( + "http.response.header.content-type", + HypertraceSemanticAttributes.httpResponseHeader("Content-Type").getKey()); + } + + @Test + public void caseInsensitiveRpcRequestMetadata() { + Assertions.assertEquals( + "rpc.request.metadata.md", HypertraceSemanticAttributes.rpcRequestMetadata("MD").getKey()); + } + + @Test + public void caseInsensitiveRpcResponseMetadata() { + Assertions.assertEquals( + "rpc.response.metadata.md", + HypertraceSemanticAttributes.rpcResponseMetadata("MD").getKey()); + } +}