From 66a85392586d8a59af254551266372d8faa6376e Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Fri, 15 Nov 2024 14:45:06 -0500 Subject: [PATCH 1/6] Update Apache, Synapse, v2/AwsSdk, JaxRsClientV1 --- .../ApacheHttpClientDecorator.java | 22 ++++++++++++++----- .../ApacheHttpClientDecorator.java | 22 ++++++++++++++----- .../aws/v2/AwsSdkClientDecorator.java | 12 ++++++++-- .../jaxrs/v1/JaxRsClientV1Decorator.java | 18 +++++++++++---- .../synapse3/SynapseClientDecorator.java | 22 ++++++++++++++----- 5 files changed, 72 insertions(+), 24 deletions(-) diff --git a/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java b/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java index 91cee1f3f85..7152ed167ad 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java @@ -3,6 +3,8 @@ import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpUriRequest; @@ -46,18 +48,26 @@ protected int status(final HttpResponse httpResponse) { @Override protected String getRequestHeader(HttpUriRequest request, String headerName) { - Header header = request.getFirstHeader(headerName); - if (null != header) { - return header.getValue(); + Header[] headers = request.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } @Override protected String getResponseHeader(HttpResponse response, String headerName) { - Header header = response.getFirstHeader(headerName); - if (null != header) { - return header.getValue(); + Header[] headers = response.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java index b1988a51de6..a8adffa1f0e 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java @@ -4,6 +4,8 @@ import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpResponse; @@ -49,18 +51,26 @@ protected int status(final HttpResponse httpResponse) { @Override protected String getRequestHeader(HttpRequest request, String headerName) { - Header header = request.getFirstHeader(headerName); - if (null != header) { - return header.getValue(); + Header[] headers = request.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } @Override protected String getResponseHeader(HttpResponse response, String headerName) { - Header header = response.getFirstHeader(headerName); - if (null != header) { - return header.getValue(); + Header[] headers = response.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } diff --git a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java index 94227b68124..4cf1c3cf8a6 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java +++ b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java @@ -450,12 +450,20 @@ public void set(SdkHttpRequest.Builder carrier, String key, String value) { @Override protected String getRequestHeader(SdkHttpRequest request, String headerName) { - return request.firstMatchingHeader(headerName).orElse(null); + List headers = request.headers().get(headerName); + if (headers != null) { + return String.join(", ", headers); + } + return null; } @Override protected String getResponseHeader(SdkHttpResponse response, String headerName) { - return response.firstMatchingHeader(headerName).orElse(null); + List headers = response.headers().get(headerName); + if (headers != null) { + return String.join(", ", headers); + } + return null; } private void awsPojoToTags(AgentSpan span, String tagsPrefix, Object pojo) { diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java b/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java index f8adab0c5ee..019a5003d01 100644 --- a/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java +++ b/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java @@ -5,6 +5,8 @@ import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; import java.net.URI; +import java.util.ArrayList; +import java.util.List; public class JaxRsClientV1Decorator extends HttpClientDecorator { @@ -41,15 +43,23 @@ protected int status(final ClientResponse clientResponse) { @Override protected String getRequestHeader(ClientRequest request, String headerName) { - Object headerValue = request.getHeaders().getFirst(headerName); - if (null != headerValue) { - return headerValue.toString(); + List headers = request.getHeaders().get(headerName); + if (null != headers) { + List result = new ArrayList<>(); + for (Object header : headers) { + result.add(header.toString()); + } + return String.join(", ", result); } return null; } @Override protected String getResponseHeader(ClientResponse response, String headerName) { - return response.getHeaders().getFirst(headerName); + List headers = response.getHeaders().get(headerName); + if (null != headers) { + return String.join(", ", headers); + } + return null; } } diff --git a/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java b/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java index 98d330bdc39..5b939401b21 100644 --- a/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java +++ b/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java @@ -5,6 +5,8 @@ import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; import java.net.URI; +import java.util.ArrayList; +import java.util.List; import org.apache.http.Header; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; @@ -47,18 +49,26 @@ protected int status(final HttpResponse response) { @Override protected String getRequestHeader(HttpRequest request, String headerName) { - Header header = request.getFirstHeader(headerName); - if (null != header) { - return header.getValue(); + Header[] headers = request.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } @Override protected String getResponseHeader(HttpResponse response, String headerName) { - Header header = response.getFirstHeader(headerName); - if (null != header) { - return header.getValue(); + Header[] headers = response.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } From 2eacb9059a0402fc7aa3944e14696b08222b63ca Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Mon, 18 Nov 2024 16:20:25 -0500 Subject: [PATCH 2/6] Update ApacheHttpAsync, Client, SpringWebfluxHttp --- .../ApacheHttpAsyncClientDecorator.java | 22 ++++++++++++++----- .../grizzly/client/ClientDecorator.java | 2 +- .../SpringWebfluxHttpClientDecorator.java | 4 ++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java b/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java index 5f9e44fd6df..705fe3bfb64 100644 --- a/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java @@ -4,6 +4,8 @@ import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; @@ -55,9 +57,13 @@ protected int status(final HttpContext context) { @Override protected String getRequestHeader(HttpUriRequest request, String headerName) { - Header header = request.getFirstHeader(headerName); - if (header != null) { - return header.getValue(); + Header[] headers = request.getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } return null; } @@ -66,9 +72,13 @@ protected String getRequestHeader(HttpUriRequest request, String headerName) { protected String getResponseHeader(HttpContext context, String headerName) { final Object responseObject = context.getAttribute(HttpCoreContext.HTTP_RESPONSE); if (responseObject instanceof HttpResponse) { - Header header = ((HttpResponse) responseObject).getFirstHeader(headerName); - if (header != null) { - return header.getValue(); + Header[] headers = ((HttpResponse) responseObject).getHeaders(headerName); + List values = new ArrayList<>(); + if (null != headers) { + for (Header header : headers) { + values.add(header.getValue()); + } + return String.join(", ", values); } } return null; diff --git a/dd-java-agent/instrumentation/grizzly-client-1.9/src/main/java/datadog/trace/instrumentation/grizzly/client/ClientDecorator.java b/dd-java-agent/instrumentation/grizzly-client-1.9/src/main/java/datadog/trace/instrumentation/grizzly/client/ClientDecorator.java index d9ac7a19fb6..a75223a8796 100644 --- a/dd-java-agent/instrumentation/grizzly-client-1.9/src/main/java/datadog/trace/instrumentation/grizzly/client/ClientDecorator.java +++ b/dd-java-agent/instrumentation/grizzly-client-1.9/src/main/java/datadog/trace/instrumentation/grizzly/client/ClientDecorator.java @@ -42,7 +42,7 @@ protected int status(final Response response) { @Override protected String getRequestHeader(Request request, String headerName) { - return request.getHeaders().getFirstValue(headerName); + return request.getHeaders().getJoinedValue(headerName, ", "); } @Override diff --git a/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java b/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java index dd91de0d112..6fe9eea08e5 100644 --- a/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java @@ -53,11 +53,11 @@ protected int status(final ClientResponse httpResponse) { @Override protected String getRequestHeader(ClientRequest request, String headerName) { - return request.headers().getFirst(headerName); + return String.join(",", request.headers().getValuesAsList(headerName)); } @Override protected String getResponseHeader(ClientResponse response, String headerName) { - return response.headers().asHttpHeaders().getFirst(headerName); + return String.join(", ", response.headers().asHttpHeaders().getValuesAsList(headerName)); } } From 570368e3e114561d50f543df1c18b2f1c36176ae Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Tue, 19 Nov 2024 18:08:20 -0500 Subject: [PATCH 3/6] Add tests --- .../trace/agent/test/base/HttpClientTest.groovy | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy index 228db2cd8e3..803e7221303 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy @@ -765,7 +765,7 @@ abstract class HttpClientTest extends VersionedNamingTestBase { def "test request header #header tag mapping"() { when: def url = server.address.resolve("/success") - def status = doRequest(method, url, [(header): value]) + def status = (value2 == null) ? doRequest(method, url, [(header): value]) : doRequest(method, url, [(header): value, (header): value2]) if (isDataStreamsEnabled()) { TEST_DATA_STREAMS_WRITER.waitForGroups(1) } @@ -788,11 +788,13 @@ abstract class HttpClientTest extends VersionedNamingTestBase { } where: - method | header | value | tags - 'GET' | 'X-Datadog-Test-Both-Header' | 'foo' | [ 'both_header_tag': 'foo' ] - 'GET' | 'X-Datadog-Test-Request-Header' | 'bar' | [ 'request_header_tag': 'bar' ] - 'GET' | 'X-Datadog-Test-Both-Header' | 'bar,baz' | [ 'both_header_tag': 'bar,baz' ] - 'GET' | 'X-Datadog-Test-Request-Header' | 'foo,bar' | [ 'request_header_tag': 'foo,bar' ] + method | header | value | value2 | tags + 'GET' | 'X-Datadog-Test-Both-Header' | 'foo' | null | [ 'both_header_tag': 'foo' ] + 'GET' | 'X-Datadog-Test-Request-Header' | 'bar' | null | [ 'request_header_tag': 'bar' ] + 'GET' | 'X-Datadog-Test-Both-Header' | 'bar,baz' | null | [ 'both_header_tag': 'bar,baz' ] + 'GET' | 'X-Datadog-Test-Request-Header' | 'foo,bar' | null | [ 'request_header_tag': 'foo,bar' ] + 'GET' | 'X-Datadog-Test-Both-Header' | 'foo' | 'foo2' | [ 'both_header_tag': 'foo, foo2' ] + 'GET' | 'X-Datadog-Test-Request-Header' | 'bar' | 'bar2' | [ 'request_header_tag': 'bar, bar2' ] } def "test response header #header tag mapping"() { From c70c133283d3886040c4ec21dd377e6c2a879637 Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Wed, 20 Nov 2024 14:39:40 -0500 Subject: [PATCH 4/6] debug --- .../client/SpringWebfluxHttpClientDecorator.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java b/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java index 6fe9eea08e5..f596ce289e6 100644 --- a/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/spring-webflux-5/src/main/java/datadog/trace/instrumentation/springwebflux/client/SpringWebfluxHttpClientDecorator.java @@ -53,11 +53,19 @@ protected int status(final ClientResponse httpResponse) { @Override protected String getRequestHeader(ClientRequest request, String headerName) { - return String.join(",", request.headers().getValuesAsList(headerName)); + System.out.println("REQUEST HEADERS: " + request.headers().getValuesAsList(headerName)); + String result = String.join(",", request.headers().getValuesAsList(headerName)); + System.out.println("RESULT: " + result); + return result; } @Override protected String getResponseHeader(ClientResponse response, String headerName) { - return String.join(", ", response.headers().asHttpHeaders().getValuesAsList(headerName)); + System.out.println( + "RESPONSE HEADERS: " + response.headers().asHttpHeaders().getValuesAsList(headerName)); + String result = + String.join(",", response.headers().asHttpHeaders().getValuesAsList(headerName)); + System.out.println("RESULT: " + result); + return result; } } From 61633a6b9ef70e1ee2d19b178de2d305eccd89c1 Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Wed, 20 Nov 2024 17:00:17 -0500 Subject: [PATCH 5/6] fix apache-httpclient-4 and 5 --- .../apachehttpclient/ApacheHttpClientDecorator.java | 2 +- .../apachehttpclient5/ApacheHttpClientDecorator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java b/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java index 7152ed167ad..0077a788a43 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpclient-4/src/main/java/datadog/trace/instrumentation/apachehttpclient/ApacheHttpClientDecorator.java @@ -63,7 +63,7 @@ protected String getRequestHeader(HttpUriRequest request, String headerName) { protected String getResponseHeader(HttpResponse response, String headerName) { Header[] headers = response.getHeaders(headerName); List values = new ArrayList<>(); - if (null != headers) { + if (headers.length > 0) { for (Header header : headers) { values.add(header.getValue()); } diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java index a8adffa1f0e..d7335a60f68 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java @@ -66,7 +66,7 @@ protected String getRequestHeader(HttpRequest request, String headerName) { protected String getResponseHeader(HttpResponse response, String headerName) { Header[] headers = response.getHeaders(headerName); List values = new ArrayList<>(); - if (null != headers) { + if (headers.length > 0) { for (Header header : headers) { values.add(header.getValue()); } From 7573e13ddb8b3a5fd8e688f9203e6f2b1cd8c856 Mon Sep 17 00:00:00 2001 From: Sarah Chen Date: Thu, 21 Nov 2024 17:09:43 -0500 Subject: [PATCH 6/6] big dump --- .../decorator/HttpClientDecorator.java | 7 +++ .../ApacheHttpAsyncClientDecorator.java | 54 +++++++++++++------ .../ApacheHttpClientDecorator.java | 15 +++++- .../groovy/ApacheHttpAsyncClient5Test.groovy | 16 ++++++ ...ApacheHttpClientResponseHandlerTest.groovy | 17 ++++++ .../test/groovy/ApacheHttpClientTest.groovy | 19 +++++++ .../aws/v2/AwsSdkClientDecorator.java | 4 +- .../jaxrs/v1/JaxRsClientV1Decorator.java | 4 +- .../synapse3/SynapseClientDecorator.java | 4 +- .../agent/test/base/HttpClientTest.groovy | 10 ++-- 10 files changed, 123 insertions(+), 27 deletions(-) diff --git a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpClientDecorator.java b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpClientDecorator.java index 834ab82e41c..33204b14028 100644 --- a/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpClientDecorator.java +++ b/dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpClientDecorator.java @@ -95,14 +95,21 @@ public AgentSpan onRequest(final AgentSpan span, final REQUEST request) { ssrfIastCheck(request); + System.out.println("hi im here"); if (CLIENT_TAG_HEADERS) { + System.out.println("now im here"); for (Map.Entry headerTag : traceConfig(span).getRequestHeaderTags().entrySet()) { + System.out.println("now im inside"); String headerValue = getRequestHeader(request, headerTag.getKey()); if (null != headerValue) { + System.out.println("now im inside inside"); + System.out.println("headerTag: " + headerTag.getValue()); + System.out.println("headerValue: " + headerValue); span.setTag(headerTag.getValue(), headerValue); } } + System.out.println("now im outside"); } } return span; diff --git a/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java b/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java index 705fe3bfb64..1f6817b4c7d 100644 --- a/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpasyncclient-4/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientDecorator.java @@ -4,8 +4,7 @@ import datadog.trace.bootstrap.instrumentation.decorator.HttpClientDecorator; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; @@ -55,16 +54,34 @@ protected int status(final HttpContext context) { return 0; } + // RUN ./gradlew :dd-java-agent:instrumentation:apache-httpasyncclient-4:test --tests + // "ApacheHttpAsyncClientV0Test" @Override protected String getRequestHeader(HttpUriRequest request, String headerName) { - Header[] headers = request.getHeaders(headerName); - List values = new ArrayList<>(); - if (null != headers) { - for (Header header : headers) { - values.add(header.getValue()); - } - return String.join(", ", values); + System.out.println("HEADERNAME: " + headerName); + System.out.println( + "ALL REQUEST HEADERS: " + + Arrays.toString(request.getAllHeaders())); // not printing first request header + System.out.println( + "SPECIFIC REQUEST HEADERS: " + Arrays.toString(request.getHeaders(headerName))); + System.out.println("FIRST REQUEST HEADER: " + request.getFirstHeader(headerName)); + + Header header = request.getFirstHeader(headerName); + if (header != null) { + System.out.println("RETURNING " + header.getValue()); + return header.getValue(); + + // Header[] headers = request.getHeaders(headerName); + // List values = new ArrayList<>(); + // if (headers.length > 0) { + // for (Header header : headers) { + // values.add(header.getValue()); + // } + // System.out.println("RETURNING " + values); + // return String.join(", ", values); + } + System.out.println("RETURNING NULL"); return null; } @@ -72,13 +89,18 @@ protected String getRequestHeader(HttpUriRequest request, String headerName) { protected String getResponseHeader(HttpContext context, String headerName) { final Object responseObject = context.getAttribute(HttpCoreContext.HTTP_RESPONSE); if (responseObject instanceof HttpResponse) { - Header[] headers = ((HttpResponse) responseObject).getHeaders(headerName); - List values = new ArrayList<>(); - if (null != headers) { - for (Header header : headers) { - values.add(header.getValue()); - } - return String.join(", ", values); + Header header = ((HttpResponse) responseObject).getFirstHeader(headerName); + if (header != null) { + return header.getValue(); + + // Header[] headers = ((HttpResponse) responseObject).getHeaders(headerName); + // List values = new ArrayList<>(); + // if (headers.length > 0) { + // for (Header header : headers) { + // values.add(header.getValue()); + // } + // return String.join(", ", values); + } } return null; diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java index d7335a60f68..3df098deecf 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/main/java/datadog/trace/instrumentation/apachehttpclient5/ApacheHttpClientDecorator.java @@ -5,6 +5,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.apache.hc.core5.http.Header; import org.apache.hc.core5.http.HttpRequest; @@ -51,27 +52,37 @@ protected int status(final HttpResponse httpResponse) { @Override protected String getRequestHeader(HttpRequest request, String headerName) { + System.out.println("HEADERNAME: " + headerName); + System.out.println( + "SPECIFIC REQUEST HEADERS: " + Arrays.toString(request.getHeaders(headerName))); Header[] headers = request.getHeaders(headerName); List values = new ArrayList<>(); if (null != headers) { for (Header header : headers) { values.add(header.getValue()); } - return String.join(", ", values); + System.out.println("RETURNING " + String.join(",", values)); + return String.join(",", values); } + System.out.println("RETURNING NULL"); return null; } @Override protected String getResponseHeader(HttpResponse response, String headerName) { + System.out.println("HEADERNAME: " + headerName); + System.out.println( + "SPECIFIC RESPONSE HEADERS: " + Arrays.toString(response.getHeaders(headerName))); Header[] headers = response.getHeaders(headerName); List values = new ArrayList<>(); if (headers.length > 0) { for (Header header : headers) { values.add(header.getValue()); } - return String.join(", ", values); + System.out.println("RETURNING " + String.join(",", values)); + return String.join(",", values); } + System.out.println("RETURNING NULL"); return null; } } diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpAsyncClient5Test.groovy b/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpAsyncClient5Test.groovy index 162be3c5467..10f8b619e67 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpAsyncClient5Test.groovy +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpAsyncClient5Test.groovy @@ -5,6 +5,7 @@ import org.apache.hc.client5.http.async.methods.SimpleHttpRequests import org.apache.hc.client5.http.config.RequestConfig import org.apache.hc.client5.http.impl.async.HttpAsyncClients import org.apache.hc.core5.http.HttpRequest +import org.apache.hc.core5.http.message.BasicHeader import spock.lang.AutoCleanup import spock.lang.Shared @@ -55,6 +56,21 @@ abstract class ApacheHttpAsyncClient5Test extends HttpCli callback?.call() return response.code } + + @Override + int doRequest(String method, URI uri, String[] headers, String body, Closure callback) { + def request = SimpleHttpRequests.create(method, uri) + request.setConfig(RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS).build()) + for (String header : headers) { + String[] keyVal = header.split(":") + request.addHeader(new BasicHeader(keyVal[0], keyVal[1])) + } + + def future = client.execute(request, null) + def response = future.get(READ_TIMEOUT_MS, TimeUnit.MILLISECONDS) + callback?.call() + return response.code + } } class ApacheHttpAsyncClient5NamingV0ForkedTest extends ApacheHttpAsyncClient5Test implements TestingGenericHttpNamingConventions.ClientV0 { diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy b/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy index cee1a8e9770..90b9dae660d 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientResponseHandlerTest.groovy @@ -53,6 +53,23 @@ class ApacheHttpClientResponseHandlerTest extends HttpClientTest implements Test return status } + @Override + int doRequest(String method, URI uri, String[] headers, String body, Closure callback) { + def request = new BasicClassicHttpRequest(method, uri) + for (String header : headers) { + String[] keyVal = header.split(":") + request.addHeader(new BasicHeader(keyVal[0], keyVal[1])) + } + + CloseableHttpResponse response = null + def status = client.execute(request, handler) + + // handler execution is included within the client span, so we can't call the callback there. + callback?.call() + + return status + } + @Override CharSequence component() { return ApacheHttpClientDecorator.DECORATE.component() diff --git a/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientTest.groovy b/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientTest.groovy index 18438e9e4df..4cbd8d1a3b9 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientTest.groovy +++ b/dd-java-agent/instrumentation/apache-httpclient-5/src/test/groovy/ApacheHttpClientTest.groovy @@ -48,6 +48,25 @@ abstract class ApacheHttpClientTest extends HttpClientTes } } + @Override + int doRequest(String method, URI uri, String[] headers, String body, Closure callback) { + def request = createRequest(method, uri) + for (String header : headers) { + String[] keyVal = header.split(":") + request.addHeader(new BasicHeader(keyVal[0], keyVal[1])) + } + + CloseableHttpResponse response = null + try { + response = executeRequest(request, uri) + callback?.call() + return response.code + } + finally { + response?.close() + } + } + abstract T createRequest(String method, URI uri) abstract CloseableHttpResponse executeRequest(T request, URI uri) diff --git a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java index 4cf1c3cf8a6..c9a98441118 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java +++ b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java @@ -451,7 +451,7 @@ public void set(SdkHttpRequest.Builder carrier, String key, String value) { @Override protected String getRequestHeader(SdkHttpRequest request, String headerName) { List headers = request.headers().get(headerName); - if (headers != null) { + if (!headers.isEmpty()) { return String.join(", ", headers); } return null; @@ -460,7 +460,7 @@ protected String getRequestHeader(SdkHttpRequest request, String headerName) { @Override protected String getResponseHeader(SdkHttpResponse response, String headerName) { List headers = response.headers().get(headerName); - if (headers != null) { + if (!headers.isEmpty()) { return String.join(", ", headers); } return null; diff --git a/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java b/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java index 019a5003d01..a7b7e4b14a9 100644 --- a/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java +++ b/dd-java-agent/instrumentation/jax-rs-client-1.1/src/main/java/datadog/trace/instrumentation/jaxrs/v1/JaxRsClientV1Decorator.java @@ -44,7 +44,7 @@ protected int status(final ClientResponse clientResponse) { @Override protected String getRequestHeader(ClientRequest request, String headerName) { List headers = request.getHeaders().get(headerName); - if (null != headers) { + if (!headers.isEmpty()) { List result = new ArrayList<>(); for (Object header : headers) { result.add(header.toString()); @@ -57,7 +57,7 @@ protected String getRequestHeader(ClientRequest request, String headerName) { @Override protected String getResponseHeader(ClientResponse response, String headerName) { List headers = response.getHeaders().get(headerName); - if (null != headers) { + if (!headers.isEmpty()) { return String.join(", ", headers); } return null; diff --git a/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java b/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java index 5b939401b21..2eebb1f94bf 100644 --- a/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java +++ b/dd-java-agent/instrumentation/synapse-3/src/main/java/datadog/trace/instrumentation/synapse3/SynapseClientDecorator.java @@ -51,7 +51,7 @@ protected int status(final HttpResponse response) { protected String getRequestHeader(HttpRequest request, String headerName) { Header[] headers = request.getHeaders(headerName); List values = new ArrayList<>(); - if (null != headers) { + if (headers.length > 0) { for (Header header : headers) { values.add(header.getValue()); } @@ -64,7 +64,7 @@ protected String getRequestHeader(HttpRequest request, String headerName) { protected String getResponseHeader(HttpResponse response, String headerName) { Header[] headers = response.getHeaders(headerName); List values = new ArrayList<>(); - if (null != headers) { + if (headers.length > 0) { for (Header header : headers) { values.add(header.getValue()); } diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy index 803e7221303..35f501f74f6 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/base/HttpClientTest.groovy @@ -144,6 +144,8 @@ abstract class HttpClientTest extends VersionedNamingTestBase { */ abstract int doRequest(String method, URI uri, Map headers = [:], String body = "", Closure callback = null) + abstract int doRequest(String method, URI uri, String[] headers, String body = "", Closure callback = null) + String keyStorePath() { server.keystorePath } @@ -765,7 +767,9 @@ abstract class HttpClientTest extends VersionedNamingTestBase { def "test request header #header tag mapping"() { when: def url = server.address.resolve("/success") - def status = (value2 == null) ? doRequest(method, url, [(header): value]) : doRequest(method, url, [(header): value, (header): value2]) + System.out.println("RUNNING HEADER, VALUE: " + header + ", " + value) + String[] headerVals = [header + ":" + value , header + ":" + value2] + def status = (value2 == null) ? doRequest(method, url, [(header): value]) : doRequest(method, url, headerVals) if (isDataStreamsEnabled()) { TEST_DATA_STREAMS_WRITER.waitForGroups(1) } @@ -793,8 +797,8 @@ abstract class HttpClientTest extends VersionedNamingTestBase { 'GET' | 'X-Datadog-Test-Request-Header' | 'bar' | null | [ 'request_header_tag': 'bar' ] 'GET' | 'X-Datadog-Test-Both-Header' | 'bar,baz' | null | [ 'both_header_tag': 'bar,baz' ] 'GET' | 'X-Datadog-Test-Request-Header' | 'foo,bar' | null | [ 'request_header_tag': 'foo,bar' ] - 'GET' | 'X-Datadog-Test-Both-Header' | 'foo' | 'foo2' | [ 'both_header_tag': 'foo, foo2' ] - 'GET' | 'X-Datadog-Test-Request-Header' | 'bar' | 'bar2' | [ 'request_header_tag': 'bar, bar2' ] + 'GET' | 'X-Datadog-Test-Both-Header' | 'bar,baz' | 'foo' | [ 'both_header_tag': 'bar,baz,foo' ] + 'GET' | 'X-Datadog-Test-Request-Header' | 'foo,bar' | 'baz' | [ 'request_header_tag': 'foo,bar,baz' ] } def "test response header #header tag mapping"() {