Passing tests.  Modify escaping of spaces in urls
MODIFY
dd-java-agent/instrumentation/google-http-client/src/main/java/datadog/trace/instrumentation/googlehttpclient/GoogleHttpClientDecorator.java
dd-java-agent/instrumentation/google-http-client/src/main/java/datadog/trace/instrumentation/googlehttpclient/GoogleHttpClientDecorator.java
@@ -16,7 +16,11 @@ public class GoogleHttpClientDecorator extends HttpClientDecorator<HttpRequest,
@Override
protected URI url(final HttpRequest httpRequest) throws URISyntaxException {
- return httpRequest.getUrl().toURI();
+ // Google uses %20 (space) instead of "+" for spaces in the fragment
+ // Add "+" back for consistency with the other http client instrumentations
+ final String url = httpRequest.getUrl().build();
+ final String fixedUrl = url.replaceAll("%20", "+");
+ return new URI(fixedUrl);
}
@Override

MODIFY
dd-java-agent/instrumentation/google-http-client/src/main/java/datadog/trace/instrumentation/googlehttpclient/GoogleHttpClientInstrumentation.java
dd-java-agent/instrumentation/google-http-client/src/main/java/datadog/trace/instrumentation/googlehttpclient/GoogleHttpClientInstrumentation.java
@@ -19,12 +19,12 @@ import io.opentracing.propagation.Format;
import io.opentracing.propagation.TextMap;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
+import java.util.Iterator;
+import java.util.Map;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
-import java.util.Iterator;
-import java.util.Map;
@AutoService(Instrumenter.class)
public class GoogleHttpClientInstrumentation extends Instrumenter.Default {
@@ -44,7 +44,7 @@ public class GoogleHttpClientInstrumentation extends Instrumenter.Default {
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.HttpClientDecorator",
- packageName + ".GoogleHttpClientClientDecorator",
+ packageName + ".GoogleHttpClientDecorator",
getClass().getName() + "$GoogleHttpClientAdvice",
getClass().getName() + "$HeadersInjectAdapter"
};
@@ -87,13 +87,14 @@ public class GoogleHttpClientInstrumentation extends Instrumenter.Default {
// If HttpRequest.setThrowExceptionOnExecuteError is set to false, there are no exceptions
// for a failed request. Thus, check the response code
- if (!response.isSuccessStatusCode()) {
+ if (response != null && !response.isSuccessStatusCode()) {
Tags.ERROR.set(span, true);
span.log(singletonMap(Fields.MESSAGE, response.getStatusMessage()));
}
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
+ span.finish();
} finally {
scope.close();
CallDepthThreadLocalMap.reset(HttpRequest.class);

ADD
dd-java-agent/instrumentation/google-http-client/src/test/groovy/GoogleHttpClientTest.groovy
+import com.google.api.client.http.GenericUrl
+import com.google.api.client.http.HttpRequest
+import com.google.api.client.http.HttpResponse
+import com.google.api.client.http.javanet.NetHttpTransport
+import datadog.trace.agent.test.base.HttpClientTest
+import datadog.trace.api.DDSpanTypes
+import datadog.trace.instrumentation.googlehttpclient.GoogleHttpClientDecorator
+import spock.lang.Shared
+
+class GoogleHttpClientTest extends HttpClientTest<GoogleHttpClientDecorator> {
+
+ @Shared
+ def requestFactory = new NetHttpTransport().createRequestFactory();
+
+ @Override
+ int doRequest(String method, URI uri, Map<String, String> headers, Closure callback) {
+ doRequest(method, uri, headers, callback, false);
+ }
+
+ int doRequest(String method, URI uri, Map<String, String> headers, Closure callback, boolean throwExceptionOnError) {
+ GenericUrl genericUrl = new GenericUrl(uri)
+
+ HttpRequest request = requestFactory.buildRequest(method, genericUrl, null)
+ request.getHeaders().putAll(headers)
+ request.setThrowExceptionOnExecuteError(throwExceptionOnError)
+
+ HttpResponse response = request.execute()
+ callback?.call()
+
+ return response.getStatusCode()
+ }
+
+ @Override
+ GoogleHttpClientDecorator decorator() {
+ return GoogleHttpClientDecorator.DECORATE
+ }
+
+ @Override
+ boolean testRedirects() {
+ // Circular redirects don't throw an exception with Google Http Client
+ return false
+ }
+
+ def "error traces when exception is not thrown"() {
+ given:
+ def uri = server.address.resolve("/error")
+
+ when:
+ def status = doRequest(method, uri)
+
+ then:
+ status == 500
+ assertTraces(2) {
+ server.distributedRequestTrace(it, 0, trace(1).last())
+ trace(1, size(1)) {
+ span(0) {
+ resourceName "$method $uri.path"
+ spanType DDSpanTypes.HTTP_CLIENT
+ errored true
+ }
+ }
+ }
+
+ where:
+ method = "GET"
+ }
+}

Passing tests.  Modify escaping of spaces in urls