From fb304a110d8001d0637c021e46226b713fd99371 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Thu, 21 Feb 2019 11:33:29 -0800 Subject: [PATCH] Migrate AWS SDK instrumentation to decorators --- .../aws/v0/AWSClientInstrumentation.java | 10 +- .../aws/v0/AwsSdkClientDecorator.java | 102 ++++++++++++++++++ .../instrumentation/aws/v0/SpanDecorator.java | 81 -------------- .../aws/v0/TracingRequestHandler.java | 52 +++------ .../v2/AbstractAwsClientInstrumentation.java | 9 +- .../aws/v2/AwsSdkClientDecorator.java | 85 +++++++++++++++ .../aws/v2/TracingExecutionInterceptor.java | 78 +++----------- .../src/test/groovy/AwsClientTest.groovy | 4 + 8 files changed, 230 insertions(+), 191 deletions(-) create mode 100644 dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AwsSdkClientDecorator.java delete mode 100644 dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/SpanDecorator.java create mode 100644 dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java diff --git a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AWSClientInstrumentation.java b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AWSClientInstrumentation.java index 81b6ba261d..5bee65abb5 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AWSClientInstrumentation.java +++ b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AWSClientInstrumentation.java @@ -8,7 +8,6 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import com.amazonaws.handlers.RequestHandler2; import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; -import io.opentracing.util.GlobalTracer; import java.util.List; import java.util.Map; import net.bytebuddy.asm.Advice; @@ -36,8 +35,11 @@ public final class AWSClientInstrumentation extends Instrumenter.Default { @Override public String[] helperClassNames() { return new String[] { - "datadog.trace.instrumentation.aws.v0.TracingRequestHandler", - "datadog.trace.instrumentation.aws.v0.SpanDecorator" + "datadog.trace.agent.decorator.BaseDecorator", + "datadog.trace.agent.decorator.ClientDecorator", + "datadog.trace.agent.decorator.HttpClientDecorator", + packageName + ".AwsSdkClientDecorator", + packageName + ".TracingRequestHandler", }; } @@ -59,7 +61,7 @@ public final class AWSClientInstrumentation extends Instrumenter.Default { } } if (!hasDDHandler) { - handlers.add(new TracingRequestHandler(GlobalTracer.get())); + handlers.add(TracingRequestHandler.INSTANCE); } } } diff --git a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AwsSdkClientDecorator.java b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AwsSdkClientDecorator.java new file mode 100644 index 0000000000..473625ac27 --- /dev/null +++ b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AwsSdkClientDecorator.java @@ -0,0 +1,102 @@ +package datadog.trace.instrumentation.aws.v0; + +import com.amazonaws.AmazonWebServiceResponse; +import com.amazonaws.Request; +import com.amazonaws.Response; +import datadog.trace.agent.decorator.HttpClientDecorator; +import datadog.trace.api.DDTags; +import io.opentracing.Span; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +class AwsSdkClientDecorator extends HttpClientDecorator { + public static final AwsSdkClientDecorator INSTANCE = new AwsSdkClientDecorator(); + + static final String COMPONENT_NAME = "java-aws-sdk"; + + private final Map serviceNames = new ConcurrentHashMap<>(); + private final Map operationNames = new ConcurrentHashMap<>(); + + @Override + public Span onRequest(final Span span, final Request request) { + // Call super first because we override the resource name below. + super.onRequest(span, request); + + final String awsServiceName = request.getServiceName(); + final Class awsOperation = request.getOriginalRequest().getClass(); + + span.setTag("aws.agent", COMPONENT_NAME); + span.setTag("aws.service", awsServiceName); + span.setTag("aws.operation", awsOperation.getSimpleName()); + span.setTag("aws.endpoint", request.getEndpoint().toString()); + + span.setTag( + DDTags.RESOURCE_NAME, + remapServiceName(awsServiceName) + "." + remapOperationName(awsOperation)); + + return span; + } + + @Override + public Span onResponse(final Span span, final Response response) { + if (response.getAwsResponse() instanceof AmazonWebServiceResponse) { + final AmazonWebServiceResponse awsResp = (AmazonWebServiceResponse) response.getAwsResponse(); + span.setTag("aws.requestId", awsResp.getRequestId()); + } + return super.onResponse(span, response); + } + + private String remapServiceName(final String serviceName) { + if (!serviceNames.containsKey(serviceName)) { + serviceNames.put(serviceName, serviceName.replace("Amazon", "").trim()); + } + return serviceNames.get(serviceName); + } + + private String remapOperationName(final Class awsOperation) { + if (!operationNames.containsKey(awsOperation)) { + operationNames.put(awsOperation, awsOperation.getSimpleName().replace("Request", "")); + } + return operationNames.get(awsOperation); + } + + @Override + protected String service() { + return COMPONENT_NAME; + } + + @Override + protected String[] instrumentationNames() { + return new String[] {"aws-sdk"}; + } + + @Override + protected String component() { + return COMPONENT_NAME; + } + + @Override + protected String method(final Request request) { + return request.getHttpMethod().name(); + } + + @Override + protected String url(final Request request) { + return request.getEndpoint().toString(); + } + + @Override + protected String hostname(final Request request) { + return null; + } + + @Override + protected Integer port(final Request request) { + return null; + } + + @Override + protected Integer status(final Response response) { + return response.getHttpResponse().getStatusCode(); + } +} diff --git a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/SpanDecorator.java b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/SpanDecorator.java deleted file mode 100644 index 6727fcc2f5..0000000000 --- a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/SpanDecorator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2017-2018 The OpenTracing 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 datadog.trace.instrumentation.aws.v0; - -import static io.opentracing.log.Fields.ERROR_OBJECT; - -import com.amazonaws.AmazonWebServiceResponse; -import com.amazonaws.Request; -import com.amazonaws.Response; -import datadog.trace.api.DDSpanTypes; -import datadog.trace.api.DDTags; -import io.opentracing.Span; -import io.opentracing.tag.Tags; -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -class SpanDecorator { - static final String COMPONENT_NAME = "java-aws-sdk"; - - private static final Map SERVICE_NAMES = new ConcurrentHashMap<>(); - private static final Map OPERATION_NAMES = new ConcurrentHashMap<>(); - - static void onRequest(final Request request, final Span span) { - Tags.COMPONENT.set(span, COMPONENT_NAME); - Tags.HTTP_METHOD.set(span, request.getHttpMethod().name()); - Tags.HTTP_URL.set(span, request.getEndpoint().toString()); - - final String awsServiceName = request.getServiceName(); - final Class awsOperation = request.getOriginalRequest().getClass(); - - span.setTag("aws.agent", COMPONENT_NAME); - span.setTag("aws.service", awsServiceName); - span.setTag("aws.operation", awsOperation.getSimpleName()); - span.setTag("aws.endpoint", request.getEndpoint().toString()); - - span.setTag(DDTags.SERVICE_NAME, COMPONENT_NAME); - span.setTag( - DDTags.RESOURCE_NAME, - remapServiceName(awsServiceName) + "." + remapOperationName(awsOperation)); - span.setTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT); - } - - static void onResponse(final Response response, final Span span) { - Tags.HTTP_STATUS.set(span, response.getHttpResponse().getStatusCode()); - if (response.getAwsResponse() instanceof AmazonWebServiceResponse) { - final AmazonWebServiceResponse awsResp = (AmazonWebServiceResponse) response.getAwsResponse(); - span.setTag("aws.requestId", awsResp.getRequestId()); - } - } - - static void onError(final Throwable throwable, final Span span) { - Tags.ERROR.set(span, Boolean.TRUE); - span.log(Collections.singletonMap(ERROR_OBJECT, throwable)); - } - - private static String remapServiceName(final String serviceName) { - if (!SERVICE_NAMES.containsKey(serviceName)) { - SERVICE_NAMES.put(serviceName, serviceName.replace("Amazon", "").trim()); - } - return SERVICE_NAMES.get(serviceName); - } - - private static String remapOperationName(final Class awsOperation) { - if (!OPERATION_NAMES.containsKey(awsOperation)) { - OPERATION_NAMES.put(awsOperation, awsOperation.getSimpleName().replace("Request", "")); - } - return OPERATION_NAMES.get(awsOperation); - } -} diff --git a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/TracingRequestHandler.java b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/TracingRequestHandler.java index 551df0e1c8..e26f29748f 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/TracingRequestHandler.java +++ b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/TracingRequestHandler.java @@ -19,39 +19,19 @@ import com.amazonaws.Response; import com.amazonaws.handlers.HandlerContextKey; import com.amazonaws.handlers.RequestHandler2; import io.opentracing.Scope; -import io.opentracing.SpanContext; -import io.opentracing.Tracer; import io.opentracing.propagation.Format; import io.opentracing.propagation.TextMapInjectAdapter; -import io.opentracing.tag.Tags; +import io.opentracing.util.GlobalTracer; /** Tracing Request Handler */ public class TracingRequestHandler extends RequestHandler2 { + public static TracingRequestHandler INSTANCE = new TracingRequestHandler(); // Note: aws1.x sdk doesn't have any truly async clients so we can store scope in request context // safely. private static final HandlerContextKey SCOPE_CONTEXT_KEY = new HandlerContextKey<>("DatadogScope"); - private final SpanContext parentContext; // for Async Client - private final Tracer tracer; - - public TracingRequestHandler(final Tracer tracer) { - parentContext = null; - this.tracer = tracer; - } - - /** - * In case of Async Client: beforeRequest runs in separate thread therefore we need to inject - * parent context to build chain - * - * @param parentContext parent context - */ - public TracingRequestHandler(final SpanContext parentContext, final Tracer tracer) { - this.parentContext = parentContext; - this.tracer = tracer; - } - @Override public AmazonWebServiceRequest beforeMarshalling(final AmazonWebServiceRequest request) { return request; @@ -60,23 +40,17 @@ public class TracingRequestHandler extends RequestHandler2 { /** {@inheritDoc} */ @Override public void beforeRequest(final Request request) { - // Note: not setting Component tag here because it is always set by SpanDecorator - final Tracer.SpanBuilder spanBuilder = - tracer.buildSpan("aws.command").withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT); - - if (parentContext != null) { - spanBuilder.asChildOf(parentContext); - } - - final Scope scope = spanBuilder.startActive(true); - SpanDecorator.onRequest(request, scope.span()); + final Scope scope = GlobalTracer.get().buildSpan("aws.command").startActive(true); + AwsSdkClientDecorator.INSTANCE.afterStart(scope.span()); + AwsSdkClientDecorator.INSTANCE.onRequest(scope.span(), request); // We inject headers at aws-client level because aws requests may be signed and adding headers // on http-client level may break signature. - tracer.inject( - scope.span().context(), - Format.Builtin.HTTP_HEADERS, - new TextMapInjectAdapter(request.getHeaders())); + GlobalTracer.get() + .inject( + scope.span().context(), + Format.Builtin.HTTP_HEADERS, + new TextMapInjectAdapter(request.getHeaders())); request.addHandlerContext(SCOPE_CONTEXT_KEY, scope); } @@ -85,7 +59,8 @@ public class TracingRequestHandler extends RequestHandler2 { @Override public void afterResponse(final Request request, final Response response) { final Scope scope = request.getHandlerContext(SCOPE_CONTEXT_KEY); - SpanDecorator.onResponse(response, scope.span()); + AwsSdkClientDecorator.INSTANCE.onResponse(scope.span(), response); + AwsSdkClientDecorator.INSTANCE.beforeFinish(scope.span()); scope.close(); } @@ -93,7 +68,8 @@ public class TracingRequestHandler extends RequestHandler2 { @Override public void afterError(final Request request, final Response response, final Exception e) { final Scope scope = request.getHandlerContext(SCOPE_CONTEXT_KEY); - SpanDecorator.onError(e, scope.span()); + AwsSdkClientDecorator.INSTANCE.onError(scope.span(), e); + AwsSdkClientDecorator.INSTANCE.beforeFinish(scope.span()); scope.close(); } } diff --git a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AbstractAwsClientInstrumentation.java b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AbstractAwsClientInstrumentation.java index 2d89c76898..654b07d859 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AbstractAwsClientInstrumentation.java +++ b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java/datadog/trace/instrumentation/aws/v2/AbstractAwsClientInstrumentation.java @@ -12,9 +12,12 @@ public abstract class AbstractAwsClientInstrumentation extends Instrumenter.Defa @Override public String[] helperClassNames() { return new String[] { - AwsClientInstrumentation.class.getPackage().getName() + ".TracingExecutionInterceptor", - AwsClientInstrumentation.class.getPackage().getName() - + ".TracingExecutionInterceptor$InjectAdapter" + "datadog.trace.agent.decorator.BaseDecorator", + "datadog.trace.agent.decorator.ClientDecorator", + "datadog.trace.agent.decorator.HttpClientDecorator", + packageName + ".AwsSdkClientDecorator", + packageName + ".TracingExecutionInterceptor", + packageName + ".TracingExecutionInterceptor$InjectAdapter" }; } } diff --git a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java new file mode 100644 index 0000000000..5ed085ad53 --- /dev/null +++ b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/AwsSdkClientDecorator.java @@ -0,0 +1,85 @@ +package datadog.trace.instrumentation.aws.v2; + +import datadog.trace.agent.decorator.HttpClientDecorator; +import datadog.trace.api.DDTags; +import io.opentracing.Span; +import software.amazon.awssdk.awscore.AwsResponse; +import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.SdkHttpResponse; + +class AwsSdkClientDecorator extends HttpClientDecorator { + public static final AwsSdkClientDecorator INSTANCE = new AwsSdkClientDecorator(); + + static final String COMPONENT_NAME = "java-aws-sdk"; + + public Span onAttributes(final Span span, final ExecutionAttributes attributes) { + + final String awsServiceName = attributes.getAttribute(SdkExecutionAttribute.SERVICE_NAME); + final String awsOperation = attributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); + + // Resource Name has to be set after the HTTP_URL because otherwise decorators overwrite it + span.setTag(DDTags.RESOURCE_NAME, awsServiceName + "." + awsOperation); + + span.setTag("aws.agent", COMPONENT_NAME); + span.setTag("aws.service", awsServiceName); + span.setTag("aws.operation", awsOperation); + + return span; + } + + // Not overriding the super. Should call both with each type of response. + public Span onResponse(final Span span, final SdkResponse response) { + if (response instanceof AwsResponse) { + span.setTag("aws.requestId", ((AwsResponse) response).responseMetadata().requestId()); + } + return span; + } + + @Override + protected String service() { + return COMPONENT_NAME; + } + + @Override + protected String[] instrumentationNames() { + return new String[] {"aws-sdk"}; + } + + @Override + protected String component() { + return COMPONENT_NAME; + } + + @Override + protected String method(final SdkHttpRequest request) { + return request.method().name(); + } + + @Override + protected String url(final SdkHttpRequest request) { + return request.protocol() + + "://" + + request.host() + + ":" + + request.port() + + request.encodedPath(); + } + + @Override + protected String hostname(final SdkHttpRequest request) { + return request.host(); + } + + @Override + protected Integer port(final SdkHttpRequest request) { + return request.port(); + } + + @Override + protected Integer status(final SdkHttpResponse response) { + return response.statusCode(); + } +} diff --git a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/TracingExecutionInterceptor.java b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/TracingExecutionInterceptor.java index 958e13e9c4..02d5313062 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/TracingExecutionInterceptor.java +++ b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/main/java8/datadog/trace/instrumentation/aws/v2/TracingExecutionInterceptor.java @@ -13,44 +13,31 @@ */ package datadog.trace.instrumentation.aws.v2; -import static io.opentracing.log.Fields.ERROR_OBJECT; - -import datadog.trace.api.DDSpanTypes; -import datadog.trace.api.DDTags; import datadog.trace.context.TraceScope; import io.opentracing.Scope; import io.opentracing.Span; import io.opentracing.Tracer; import io.opentracing.propagation.Format; import io.opentracing.propagation.TextMap; -import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.function.Consumer; -import software.amazon.awssdk.awscore.AwsResponse; -import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; import software.amazon.awssdk.core.interceptor.Context; import software.amazon.awssdk.core.interceptor.ExecutionAttribute; import software.amazon.awssdk.core.interceptor.ExecutionAttributes; import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute; import software.amazon.awssdk.http.SdkHttpRequest; /** AWS request execution interceptor */ public class TracingExecutionInterceptor implements ExecutionInterceptor { - private static final TracingExecutionInterceptor INSTANCE = new TracingExecutionInterceptor(); // Note: it looks like this lambda doesn't get generated as a separate class file so we do not // need to inject helper for it. private static final Consumer - OVERRIDE_CONFIGURATION_CONSUMER = builder -> builder.addExecutionInterceptor(INSTANCE); - - static final String COMPONENT_NAME = "java-aws-sdk"; + OVERRIDE_CONFIGURATION_CONSUMER = + builder -> builder.addExecutionInterceptor(new TracingExecutionInterceptor()); private static final ExecutionAttribute SPAN_ATTRIBUTE = new ExecutionAttribute<>("DatadogSpan"); @@ -58,16 +45,9 @@ public class TracingExecutionInterceptor implements ExecutionInterceptor { @Override public void beforeExecution( final Context.BeforeExecution context, final ExecutionAttributes executionAttributes) { - final Tracer tracer = GlobalTracer.get(); - - final Tracer.SpanBuilder builder = - tracer - .buildSpan("aws.command") - .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) - .withTag(Tags.COMPONENT.getKey(), COMPONENT_NAME) - .withTag(DDTags.SERVICE_NAME, COMPONENT_NAME) - .withTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT); - executionAttributes.putAttribute(SPAN_ATTRIBUTE, builder.start()); + final Span span = GlobalTracer.get().buildSpan("aws.command").start(); + AwsSdkClientDecorator.INSTANCE.afterStart(span); + executionAttributes.putAttribute(SPAN_ATTRIBUTE, span); } @Override @@ -76,35 +56,8 @@ public class TracingExecutionInterceptor implements ExecutionInterceptor { final Span span = executionAttributes.getAttribute(SPAN_ATTRIBUTE); final SdkHttpRequest httpRequest = context.httpRequest(); - Tags.HTTP_METHOD.set(span, httpRequest.method().name()); - - try { - final URI requestUri = httpRequest.getUri(); - final String uri = - new URI( - requestUri.getScheme(), - null, - requestUri.getHost(), - requestUri.getPort(), - requestUri.getPath(), - null, - null) - .toString(); - Tags.HTTP_URL.set(span, uri); - } catch (final URISyntaxException e) { - Tags.HTTP_URL.set(span, "failed-to-parse"); - } - final String awsServiceName = - executionAttributes.getAttribute(SdkExecutionAttribute.SERVICE_NAME); - final String awsOperation = - executionAttributes.getAttribute(SdkExecutionAttribute.OPERATION_NAME); - - // Resource Name has to be set after the HTTP_URL because otherwise decorators overwrite it - span.setTag(DDTags.RESOURCE_NAME, awsServiceName + "." + awsOperation); - - span.setTag("aws.agent", COMPONENT_NAME); - span.setTag("aws.service", awsServiceName); - span.setTag("aws.operation", awsOperation); + AwsSdkClientDecorator.INSTANCE.onRequest(span, httpRequest); + AwsSdkClientDecorator.INSTANCE.onAttributes(span, executionAttributes); } @Override @@ -132,23 +85,18 @@ public class TracingExecutionInterceptor implements ExecutionInterceptor { public void afterExecution( final Context.AfterExecution context, final ExecutionAttributes executionAttributes) { final Span span = executionAttributes.getAttribute(SPAN_ATTRIBUTE); - try { - Tags.HTTP_STATUS.set(span, context.httpResponse().statusCode()); - final SdkResponse response = context.response(); - if (response instanceof AwsResponse) { - span.setTag("aws.requestId", ((AwsResponse) response).responseMetadata().requestId()); - } - } finally { - span.finish(); - } + // Call onResponse on both types of responses: + AwsSdkClientDecorator.INSTANCE.onResponse(span, context.response()); + AwsSdkClientDecorator.INSTANCE.onResponse(span, context.httpResponse()); + AwsSdkClientDecorator.INSTANCE.beforeFinish(span); + span.finish(); } @Override public void onExecutionFailure( final Context.FailedExecution context, final ExecutionAttributes executionAttributes) { final Span span = executionAttributes.getAttribute(SPAN_ATTRIBUTE); - Tags.ERROR.set(span, Boolean.TRUE); - span.log(Collections.singletonMap(ERROR_OBJECT, context.exception())); + AwsSdkClientDecorator.INSTANCE.onError(span, context.exception()); } public static Consumer getOverrideConfigurationConsumer() { diff --git a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/test/groovy/AwsClientTest.groovy b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/test/groovy/AwsClientTest.groovy index 946bc2189d..a05a2c6004 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/test/groovy/AwsClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java-sdk-2.2/src/test/groovy/AwsClientTest.groovy @@ -76,6 +76,8 @@ class AwsClientTest extends AgentTestRunner { "$Tags.HTTP_STATUS.key" 200 "$Tags.HTTP_URL.key" expectedUrl "$Tags.HTTP_METHOD.key" "$method" + "$Tags.PEER_HOSTNAME.key" "localhost" + "$Tags.PEER_PORT.key" server.address.port "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT "aws.service" "$service" @@ -167,6 +169,8 @@ class AwsClientTest extends AgentTestRunner { "$Tags.HTTP_STATUS.key" 200 "$Tags.HTTP_URL.key" expectedUrl "$Tags.HTTP_METHOD.key" "$method" + "$Tags.PEER_HOSTNAME.key" "localhost" + "$Tags.PEER_PORT.key" server.address.port "$Tags.SPAN_KIND.key" Tags.SPAN_KIND_CLIENT "$DDTags.SPAN_TYPE" DDSpanTypes.HTTP_CLIENT "aws.service" "$service"