Trap agent errors in DDTracingClientExec
MODIFY
dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/DDTracingClientExec.java
dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/DDTracingClientExec.java
@@ -15,6 +15,7 @@ import java.net.URI;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
+import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.client.RedirectStrategy;
@@ -30,6 +31,7 @@ import org.apache.http.impl.execchain.ClientExecChain;
* the next to last. Note that {@link org.apache.http.impl.execchain.RedirectExec} is invoked before
* so this exec has to deal with redirects.
*/
+@Slf4j
public class DDTracingClientExec implements ClientExecChain {
private static final String COMPONENT_NAME = "apache-httpclient";
/**
@@ -123,15 +125,20 @@ public class DDTracingClientExec implements ClientExecChain {
final HttpClientContext clientContext,
final HttpExecutionAware execAware)
throws IOException, HttpException {
- final Scope networkScope =
+ Scope networkScope = null;
+ Span networkSpan = null;
+ try {
+ // This handlers runs untrapped in the client code
+ // so we must ensure any unexpected agent errors are caught.
+ try {
+ networkScope =
tracer
.buildSpan(request.getMethod())
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT)
.asChildOf(parentScope.span())
.startActive(true);
-
- final Span networkSpan = networkScope.span();
+ networkSpan = networkScope.span();
final boolean awsClientCall = request.getHeaders("amz-sdk-invocation-id").length > 0;
// AWS calls are often signed, so we can't add headers without breaking the signature.
@@ -141,20 +148,30 @@ public class DDTracingClientExec implements ClientExecChain {
Format.Builtin.HTTP_HEADERS,
new HttpHeadersInjectAdapter(request));
}
-
- try {
// request tags
Tags.HTTP_METHOD.set(networkSpan, request.getRequestLine().getMethod());
- final URI uri = request.getURI();
Tags.HTTP_URL.set(networkSpan, request.getRequestLine().getUri());
+ final URI uri = request.getURI();
+ // zuul users have encountered cases where getURI returns null
+ if (null != uri) {
Tags.PEER_PORT.set(networkSpan, uri.getPort() == -1 ? 80 : uri.getPort());
Tags.PEER_HOSTNAME.set(networkSpan, uri.getHost());
+ }
+ } catch (Exception e) {
+ log.debug("failed to create network span", e);
+ }
final CloseableHttpResponse response =
requestExecutor.execute(route, request, clientContext, execAware);
+ try {
// response tags
+ if (null != networkSpan) {
Tags.HTTP_STATUS.set(networkSpan, response.getStatusLine().getStatusCode());
+ }
+ } catch (Exception e) {
+ log.debug("failed to set network span status", e);
+ }
return response;
} catch (IOException | HttpException | RuntimeException e) {
@@ -164,9 +181,11 @@ public class DDTracingClientExec implements ClientExecChain {
throw e;
} finally {
+ if (null != networkScope) {
networkScope.close();
}
}
+ }
public static class HttpHeadersInjectAdapter implements TextMap {

Trap agent errors in DDTracingClientExec