From 1ee1918e8ad61c98c0b107100e92a331fd116d53 Mon Sep 17 00:00:00 2001 From: Nugusbayev Kanagat Date: Thu, 19 Oct 2023 14:15:50 +0600 Subject: [PATCH 1/4] access SdkClientConfiguration via reflection from base class field --- ...BaseAsyncClientHandlerInstrumentation.java | 9 +++++- .../BaseSyncClientHandlerInstrumentation.java | 4 ++- .../apm/agent/awssdk/v2/helper/SQSHelper.java | 29 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java index 8fc839664d..3cd47e868a 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java @@ -35,8 +35,14 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.ExecutionContext; +import software.amazon.awssdk.core.internal.handler.BaseAsyncClientHandler; +import software.amazon.awssdk.core.internal.handler.BaseClientHandler; import software.amazon.awssdk.core.internal.http.TransformingAsyncResponseHandler; +import software.amazon.awssdk.utils.internal.ReflectionUtils; +import javax.annotation.Nonnull; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.net.URI; import java.util.Collection; import java.util.Collections; @@ -75,9 +81,10 @@ public static class AdviceClass { public static TransformingAsyncResponseHandler enterDoExecute(@Advice.Argument(value = 0) ClientExecutionParams clientExecutionParams, @Advice.Argument(value = 1) ExecutionContext executionContext, @Advice.Argument(value = 2) TransformingAsyncResponseHandler responseHandler, - @Advice.FieldValue("clientConfiguration") SdkClientConfiguration clientConfiguration) { + @Advice.This BaseAsyncClientHandler thiz) throws Throwable { String awsService = executionContext.executionAttributes().getAttribute(AwsSignerExecutionAttribute.SERVICE_NAME); SdkRequest sdkRequest = clientExecutionParams.getInput(); + SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(thiz); URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT); Span span = null; boolean isSqs = false; diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java index b49d4a009b..e0f8f4ef3c 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java @@ -39,6 +39,7 @@ import software.amazon.awssdk.core.client.config.SdkClientOption; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.ExecutionContext; +import software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler; import javax.annotation.Nullable; import java.net.URI; @@ -85,9 +86,10 @@ public static class AdviceClass { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static Object enterDoExecute(@Advice.Argument(value = 0) ClientExecutionParams clientExecutionParams, @Advice.Argument(value = 1) ExecutionContext executionContext, - @Advice.FieldValue("clientConfiguration") SdkClientConfiguration clientConfiguration) { + @Advice.This BaseSyncClientHandler thiz) throws Throwable { String awsService = executionContext.executionAttributes().getAttribute(AwsSignerExecutionAttribute.SERVICE_NAME); SdkRequest sdkRequest = clientExecutionParams.getInput(); + SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(thiz); URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT); Span span = null; boolean isSqs = false; diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java index 52652e47d7..08d7411598 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java @@ -26,8 +26,10 @@ import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; +import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.ExecutionContext; +import software.amazon.awssdk.core.internal.handler.BaseClientHandler; import software.amazon.awssdk.services.sqs.model.Message; import software.amazon.awssdk.services.sqs.model.MessageAttributeValue; import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest; @@ -36,7 +38,10 @@ import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry; import software.amazon.awssdk.services.sqs.model.SendMessageRequest; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -182,4 +187,28 @@ public void handleReceivedMessages(Span span, @Nullable SdkRequest sdkRequest SQSHelper.getInstance().handleReceivedMessages(span, ((ReceiveMessageRequest) sdkRequest).queueUrl(), ((ReceiveMessageResponse) sdkResponse).messages()); } } + + @Nullable + public SdkClientConfiguration findClientConfiguration(@Nonnull BaseClientHandler thiz) throws Throwable { + + Class subclass = thiz.getClass(); + Class targetClass = BaseClientHandler.class; + Class currentClass = subclass; + SdkClientConfiguration sdkClientConfiguration = null; + while (null != currentClass) { + if (targetClass.equals(currentClass)) { + Field clientConfigurationField = currentClass.getDeclaredField("clientConfiguration"); + if (null != clientConfigurationField) { + int fieldModifier = clientConfigurationField.getModifiers(); + if (Modifier.isPrivate(fieldModifier)) { + clientConfigurationField.setAccessible(true); + } + sdkClientConfiguration = (SdkClientConfiguration) clientConfigurationField.get(thiz); + } + break; + } + currentClass = currentClass.getSuperclass(); + } + return sdkClientConfiguration; + } } From e1b74af0c8e479839d42c7d2ef16e2fda606267f Mon Sep 17 00:00:00 2001 From: Nugusbayev Kanagat Date: Thu, 19 Oct 2023 14:58:33 +0600 Subject: [PATCH 2/4] minor refactores --- .../apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml | 2 +- ...BaseAsyncClientHandlerInstrumentation.java | 5 +++- .../BaseSyncClientHandlerInstrumentation.java | 5 +++- .../apm/agent/awssdk/v2/helper/SQSHelper.java | 29 ++++++++++++------- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml index 531467cc31..2b399d0fdd 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/pom.xml @@ -13,7 +13,7 @@ ${project.basedir}/../../.. - 2.20.157 + 2.21.0 2.0.0 8 diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java index 3cd47e868a..5c93336ea0 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java @@ -84,7 +84,10 @@ public static TransformingAsyncResponseHandler enterDoExecute(@Advice.Argumen @Advice.This BaseAsyncClientHandler thiz) throws Throwable { String awsService = executionContext.executionAttributes().getAttribute(AwsSignerExecutionAttribute.SERVICE_NAME); SdkRequest sdkRequest = clientExecutionParams.getInput(); - SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(thiz); + SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(clientExecutionParams, thiz); + if (null == clientConfiguration) { + // handle null + } URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT); Span span = null; boolean isSqs = false; diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java index e0f8f4ef3c..c41e64e1b0 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java @@ -89,7 +89,10 @@ public static Object enterDoExecute(@Advice.Argument(value = 0) ClientExecutionP @Advice.This BaseSyncClientHandler thiz) throws Throwable { String awsService = executionContext.executionAttributes().getAttribute(AwsSignerExecutionAttribute.SERVICE_NAME); SdkRequest sdkRequest = clientExecutionParams.getInput(); - SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(thiz); + SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(clientExecutionParams, thiz); + if (null == clientConfiguration) { + // handle null + } URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT); Span span = null; boolean isSqs = false; diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java index 08d7411598..4702c6ce9c 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/helper/SQSHelper.java @@ -18,12 +18,15 @@ */ package co.elastic.apm.agent.awssdk.v2.helper; +import co.elastic.apm.agent.awssdk.common.AbstractMessageIteratorWrapper; import co.elastic.apm.agent.awssdk.common.AbstractSQSInstrumentationHelper; import co.elastic.apm.agent.tracer.ElasticContext; import co.elastic.apm.agent.tracer.GlobalTracer; import co.elastic.apm.agent.tracer.Span; import co.elastic.apm.agent.tracer.Tracer; import co.elastic.apm.agent.tracer.dispatch.TextHeaderSetter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; @@ -54,6 +57,8 @@ public class SQSHelper extends AbstractSQSInstrumentationHelper span, @Nullable SdkRequest sdkRequest } @Nullable - public SdkClientConfiguration findClientConfiguration(@Nonnull BaseClientHandler thiz) throws Throwable { - - Class subclass = thiz.getClass(); + public SdkClientConfiguration findClientConfiguration(ClientExecutionParams clientExecutionParams, @Nonnull BaseClientHandler thiz) throws Throwable { + SdkClientConfiguration sdkClientConfiguration = clientExecutionParams.requestConfiguration(); + if (sdkClientConfiguration != null) { + return sdkClientConfiguration; + } Class targetClass = BaseClientHandler.class; - Class currentClass = subclass; - SdkClientConfiguration sdkClientConfiguration = null; + Class currentClass = thiz.getClass(); while (null != currentClass) { if (targetClass.equals(currentClass)) { Field clientConfigurationField = currentClass.getDeclaredField("clientConfiguration"); - if (null != clientConfigurationField) { - int fieldModifier = clientConfigurationField.getModifiers(); - if (Modifier.isPrivate(fieldModifier)) { - clientConfigurationField.setAccessible(true); - } - sdkClientConfiguration = (SdkClientConfiguration) clientConfigurationField.get(thiz); + int fieldModifier = clientConfigurationField.getModifiers(); + if (Modifier.isPrivate(fieldModifier)) { + clientConfigurationField.setAccessible(true); } + sdkClientConfiguration = (SdkClientConfiguration) clientConfigurationField.get(thiz); break; } currentClass = currentClass.getSuperclass(); } + if (sdkClientConfiguration == null) { + logger.warn("Cannot identify SdkClientConfiguration"); + } return sdkClientConfiguration; } } From 4f877de880d43bfe90122e875e94ded342ed7655 Mon Sep 17 00:00:00 2001 From: Nugusbayev Kanagat Date: Thu, 19 Oct 2023 15:06:50 +0600 Subject: [PATCH 3/4] added null handle --- .../agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java | 2 +- .../agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java index 5c93336ea0..38d9f8cb0c 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseAsyncClientHandlerInstrumentation.java @@ -86,7 +86,7 @@ public static TransformingAsyncResponseHandler enterDoExecute(@Advice.Argumen SdkRequest sdkRequest = clientExecutionParams.getInput(); SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(clientExecutionParams, thiz); if (null == clientConfiguration) { - // handle null + return responseHandler; } URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT); Span span = null; diff --git a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java index c41e64e1b0..5f1cfd1afc 100644 --- a/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java +++ b/apm-agent-plugins/apm-aws-sdk/apm-aws-sdk-2-plugin/src/main/java/co/elastic/apm/agent/awssdk/v2/BaseSyncClientHandlerInstrumentation.java @@ -91,7 +91,7 @@ public static Object enterDoExecute(@Advice.Argument(value = 0) ClientExecutionP SdkRequest sdkRequest = clientExecutionParams.getInput(); SdkClientConfiguration clientConfiguration = SQSHelper.getInstance().findClientConfiguration(clientExecutionParams, thiz); if (null == clientConfiguration) { - // handle null + return null; } URI uri = clientConfiguration.option(SdkClientOption.ENDPOINT); Span span = null; From d0650fce1a2b65f4bb9598357cdfacf54eafdaf0 Mon Sep 17 00:00:00 2001 From: Nugusbayev Kanagat Date: Thu, 19 Oct 2023 15:11:24 +0600 Subject: [PATCH 4/4] added entry to changelog --- CHANGELOG.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 0a8fb52ffb..fcdfaadf3c 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -38,6 +38,7 @@ Use subheadings with the "=====" level for adding notes for unreleased changes: [float] ===== Bug fixes * Fixed too many spans being created for `HTTPUrlConnection` requests with method `HEAD` - {pull}3353[#3353] +* Fixed aws sdk v2 instrumentation due to internal changes - {pull}3374[#3374] [[release-notes-1.x]] === Java Agent version 1.x