From ab8617feaf87410c0cbb037dfdf2b63bd45e8fc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Mon, 3 Jul 2023 18:05:38 +0200 Subject: [PATCH 1/6] Skeleton files --- .../awssdk/v1_11/SqsAdviceBridge.java | 6 ++ .../AbstractAwsSdkInstrumentationModule.java | 59 +++++++++++++++++++ .../v1_11/SqsInstrumentationModule.java | 38 ++++++++++++ .../awssdk/v1_11/PluginImplUtil.java | 49 +++++++++++++++ .../awssdk/v1_11/SqsAccess.java | 2 + .../instrumentation/awssdk/v1_11/SqsImpl.java | 2 + 6 files changed, 156 insertions(+) create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java new file mode 100644 index 000000000000..7a98a9461df6 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java @@ -0,0 +1,6 @@ +package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; + +public class SqsAdviceBridge { + public static void referenceForMuzzleOnly() { + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java new file mode 100644 index 000000000000..25b7b5c06c38 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java @@ -0,0 +1,59 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; + +import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static java.util.Collections.singletonList; +import static net.bytebuddy.matcher.ElementMatchers.named; + +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import java.util.List; +import net.bytebuddy.description.type.TypeDescription; +import net.bytebuddy.matcher.ElementMatcher; + +abstract class AbstractAwsSdkInstrumentationModule extends InstrumentationModule { + + protected AbstractAwsSdkInstrumentationModule(String additionalInstrumentationName) { + super("aws-sdk", "aws-sdk-2.2", additionalInstrumentationName); + } + + @Override + public boolean isHelperClass(String className) { + return className.startsWith("io.opentelemetry.contrib.awsxray."); + } + + @Override + public ElementMatcher.Junction classLoaderMatcher() { + // We don't actually transform it but want to make sure we only apply the instrumentation when + // our key dependency is present. + return hasClassesNamed("software.amazon.awssdk.core.interceptor.ExecutionInterceptor"); + } + + @Override + public List typeInstrumentations() { + return singletonList(new ResourceInjectingTypeInstrumentation()); + } + + abstract void doTransform(TypeTransformer transformer); + + // A type instrumentation is needed to trigger resource injection. + public class ResourceInjectingTypeInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher typeMatcher() { + // This is essentially the entry point of the AWS SDK, all clients implement it. We can ensure + // our interceptor service definition is injected as early as possible if we typematch against + // it. + return named("software.amazon.awssdk.core.SdkClient"); + } + + @Override + public void transform(TypeTransformer transformer) { + doTransform(transformer); + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java new file mode 100644 index 000000000000..3fdab6da5d2f --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; + +import static net.bytebuddy.matcher.ElementMatchers.none; + +import com.google.auto.service.AutoService; +import io.opentelemetry.instrumentation.awssdk.v2_2.SqsAdviceBridge; +import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; +import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import net.bytebuddy.asm.Advice; + +@AutoService(InstrumentationModule.class) +public class SqsInstrumentationModule extends AbstractAwsSdkInstrumentationModule { + + public SqsInstrumentationModule() { + super("aws-sdk-2.2-sqs"); + } + + @Override + public void doTransform(TypeTransformer transformer) { + transformer.applyAdviceToMethod( + none(), SqsInstrumentationModule.class.getName() + "$RegisterAdvice"); + } + + @SuppressWarnings("unused") + public static class RegisterAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit() { + // (indirectly) using SqsImpl class here to make sure it is available from SqsAccess + // (injected into app classloader) and checked by Muzzle + SqsAdviceBridge.referenceForMuzzleOnly(); + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java new file mode 100644 index 000000000000..f5043ae13257 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java @@ -0,0 +1,49 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v2_2; + +import java.util.logging.Level; +import java.util.logging.Logger; + +final class PluginImplUtil { + private PluginImplUtil() {} + + private static final Logger logger = Logger.getLogger(PluginImplUtil.class.getName()); + + /** + * Check if the given {@code moduleNameImpl} is present. + * + *

For library instrumentations, the Impls will always be available but might fail to load if + * the corresponding SDK classes are not on the class path. For javaagent, the Impl is available + * only when the corresponding InstrumentationModule was successfully applied (muzzle passed). + * + *

Note that an present-but-incompatible library can only be detected by Muzzle. In + * library-mode, users need to ensure they are using a compatible SDK (component) versions + * themselves. + * + * @param implSimpleClassName The simple name of the impl class, e.g. {@code "SqsImpl"}. * + */ + static boolean isImplPresent(String implSimpleClassName) { + // We use getName().replace() instead of getPackage() because the latter is not guaranteed to + // work in all cases (e.g., we might be loaded into a custom classloader that doesn't handle it) + String implFullClassName = + PluginImplUtil.class.getName().replace(".PluginImplUtil", "." + implSimpleClassName); + try { + // using package name here because library instrumentation classes are relocated when embedded + // in the agent + Class.forName(implFullClassName); + return true; + } catch (ClassNotFoundException | LinkageError e) { + // ClassNotFoundException will happen when muzzle disabled us in javaagent mode; LinkageError + // (most likely NoClassDefFoundError) should happen when the class is loaded in library mode + // (where it is always available) but a dependency failed to load (most likely because the + // corresponding SDK dependency is not on the class path). + logger.log( + Level.FINE, e, () -> implFullClassName + " not present, probably incompatible version"); + return false; + } + } +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java new file mode 100644 index 000000000000..7df78ea90a75 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java @@ -0,0 +1,2 @@ +package io.opentelemetry.instrumentation.awssdk.v1_11;public class SqsAccess { +} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java new file mode 100644 index 000000000000..489e7de4dc25 --- /dev/null +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java @@ -0,0 +1,2 @@ +package io.opentelemetry.instrumentation.awssdk.v1_11;public class SqsImpl { +} From 3be72d162daf7106bb26a40dfe31739bfc6f0e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Mon, 3 Jul 2023 18:06:05 +0200 Subject: [PATCH 2/6] Add/copy initial scaffholding --- .../aws-sdk-1.11/javaagent/build.gradle.kts | 18 +++++++++++++ .../awssdk/v1_11/SqsAdviceBridge.java | 13 ++++++++-- .../AbstractAwsSdkInstrumentationModule.java | 9 ++++--- .../v1_11/AwsSdkInstrumentationModule.java | 2 +- .../v1_11/SqsInstrumentationModule.java | 6 ++--- .../aws-sdk-1.11/library/build.gradle.kts | 3 ++- .../awssdk/v1_11/PluginImplUtil.java | 4 +-- .../awssdk/v1_11/SqsAccess.java | 20 ++++++++++++++- .../instrumentation/awssdk/v1_11/SqsImpl.java | 25 ++++++++++++++++++- .../awssdk/v1_11/TracingRequestHandler.java | 2 +- settings.gradle.kts | 25 +++++++++++++------ 11 files changed, 104 insertions(+), 23 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts index b654433cefe6..f4b40b6922d5 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts @@ -15,7 +15,25 @@ muzzle { module.set("aws-java-sdk-core") versions.set("[1.10.33,)") assertInverse.set(true) + + excludeInstrumentationName("aws-sdk-1.11-sqs") + } + + + fail { + group.set("com.amazonaws") + module.set("aws-java-sdk-core") + versions.set("[1.10.33,)") + + excludeInstrumentationName("aws-sdk-1.11-core") } + + pass { + group.set("com.amazonaws") + module.set("aws-java-sdk-sqs") + versions.set("[1.10.33,)") + } + } dependencies { diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java index 7a98a9461df6..efa6fe9a3428 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAdviceBridge.java @@ -1,6 +1,15 @@ -package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +public final class SqsAdviceBridge { + private SqsAdviceBridge() {} -public class SqsAdviceBridge { public static void referenceForMuzzleOnly() { + throw new UnsupportedOperationException( + SqsImpl.class.getName() + " referencing for muzzle, should never be actually called"); } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java index 25b7b5c06c38..0e515eb28abf 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AbstractAwsSdkInstrumentationModule.java @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; +package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; import static java.util.Collections.singletonList; @@ -16,10 +16,11 @@ import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; +// TODO: Copy & paste with only trivial adaptions from v2 abstract class AbstractAwsSdkInstrumentationModule extends InstrumentationModule { protected AbstractAwsSdkInstrumentationModule(String additionalInstrumentationName) { - super("aws-sdk", "aws-sdk-2.2", additionalInstrumentationName); + super("aws-sdk", "aws-sdk-1.11", additionalInstrumentationName); } @Override @@ -31,7 +32,7 @@ public boolean isHelperClass(String className) { public ElementMatcher.Junction classLoaderMatcher() { // We don't actually transform it but want to make sure we only apply the instrumentation when // our key dependency is present. - return hasClassesNamed("software.amazon.awssdk.core.interceptor.ExecutionInterceptor"); + return hasClassesNamed("com.amazonaws.AmazonWebServiceClient"); } @Override @@ -48,7 +49,7 @@ public ElementMatcher typeMatcher() { // This is essentially the entry point of the AWS SDK, all clients implement it. We can ensure // our interceptor service definition is injected as early as possible if we typematch against // it. - return named("software.amazon.awssdk.core.SdkClient"); + return named("com.amazonaws.AmazonWebServiceClient"); } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java index 99d72487993e..048bbdfc41a6 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/AwsSdkInstrumentationModule.java @@ -15,7 +15,7 @@ @AutoService(InstrumentationModule.class) public class AwsSdkInstrumentationModule extends InstrumentationModule { public AwsSdkInstrumentationModule() { - super("aws-sdk", "aws-sdk-1.11"); + super("aws-sdk", "aws-sdk-1.11", "aws-sdk-1.11-core"); } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java index 3fdab6da5d2f..cc61cf6d9cc0 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SqsInstrumentationModule.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2; +package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11; import static net.bytebuddy.matcher.ElementMatchers.none; import com.google.auto.service.AutoService; -import io.opentelemetry.instrumentation.awssdk.v2_2.SqsAdviceBridge; +import io.opentelemetry.instrumentation.awssdk.v1_11.SqsAdviceBridge; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -17,7 +17,7 @@ public class SqsInstrumentationModule extends AbstractAwsSdkInstrumentationModule { public SqsInstrumentationModule() { - super("aws-sdk-2.2-sqs"); + super("aws-sdk-1.11-sqs"); } @Override diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts index 99277d1ea885..aa9e0634a867 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/build.gradle.kts @@ -6,6 +6,8 @@ dependencies { implementation("io.opentelemetry.contrib:opentelemetry-aws-xray-propagator") library("com.amazonaws:aws-java-sdk-core:1.11.0") + library("com.amazonaws:aws-java-sdk-sqs:1.11.106") + compileOnly(project(":muzzle")) testImplementation(project(":instrumentation:aws-sdk:aws-sdk-1.11:testing")) @@ -15,5 +17,4 @@ dependencies { testLibrary("com.amazonaws:aws-java-sdk-kinesis:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-dynamodb:1.11.106") testLibrary("com.amazonaws:aws-java-sdk-sns:1.11.106") - testLibrary("com.amazonaws:aws-java-sdk-sqs:1.11.106") } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java index f5043ae13257..d16ce1983efc 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -package io.opentelemetry.instrumentation.awssdk.v2_2; +package io.opentelemetry.instrumentation.awssdk.v1_11; import java.util.logging.Level; import java.util.logging.Logger; -final class PluginImplUtil { +final class PluginImplUtil { // TODO: Copy & paste from v2 private PluginImplUtil() {} private static final Logger logger = Logger.getLogger(PluginImplUtil.class.getName()); diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java index 7df78ea90a75..d4a4995c7f80 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java @@ -1,2 +1,20 @@ -package io.opentelemetry.instrumentation.awssdk.v1_11;public class SqsAccess { +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +import com.amazonaws.AmazonWebServiceRequest; +import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle; + +final class SqsAccess { + private SqsAccess() {} + + private static final boolean enabled = PluginImplUtil.isImplPresent("SqsImpl"); + + @NoMuzzle + public static boolean isReceiveMessageRequest(AmazonWebServiceRequest originalRequest) { + return enabled && SqsImpl.isReceiveMessageRequest(originalRequest); + } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java index 489e7de4dc25..4f2f1c929222 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java @@ -1,2 +1,25 @@ -package io.opentelemetry.instrumentation.awssdk.v1_11;public class SqsImpl { +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.awssdk.v1_11; + +import com.amazonaws.AmazonWebServiceRequest; +import com.amazonaws.services.sqs.AmazonSQS; +import com.amazonaws.services.sqs.model.ReceiveMessageRequest; + +final class SqsImpl { + static { + // Force loading of SqsClient; this ensures that an exception is thrown at this point when the + // SQS library is not present, which will cause SqsAccess to have enabled=false in library mode. + @SuppressWarnings("unused") + String ensureLoadedDummy = AmazonSQS.class.getName(); + } + + private SqsImpl() {} + + public static boolean isReceiveMessageRequest(AmazonWebServiceRequest originalRequest) { + return originalRequest instanceof ReceiveMessageRequest; + } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java index a6755552197c..e15f4cfb5725 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java @@ -70,7 +70,7 @@ public AmazonWebServiceRequest beforeMarshalling(AmazonWebServiceRequest request @Override public void afterResponse(Request request, Response response) { - if (SqsReceiveMessageRequestAccess.isInstance(request.getOriginalRequest())) { + if (SqsAccess.isReceiveMessageRequest(request.getOriginalRequest())) { afterConsumerResponse(request, response); } finish(request, response, null); diff --git a/settings.gradle.kts b/settings.gradle.kts index cdb637ca3426..4c03e2759be9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -120,6 +120,7 @@ include(":testing-common") include(":testing-common:integration-tests") include(":testing-common:library-for-integration-tests") +/* // smoke tests include(":smoke-tests") include(":smoke-tests:images:fake-backend") @@ -131,7 +132,8 @@ include(":smoke-tests:images:servlet") hideFromDependabot(":smoke-tests:images:servlet:servlet-3.0") hideFromDependabot(":smoke-tests:images:servlet:servlet-5.0") hideFromDependabot(":smoke-tests:images:spring-boot") - +*/ +/* hideFromDependabot("instrumentation:akka:akka-actor-2.3:javaagent") hideFromDependabot(":instrumentation:akka:akka-actor-fork-join-2.5:javaagent") hideFromDependabot(":instrumentation:akka:akka-http-10.0:javaagent") @@ -142,16 +144,19 @@ hideFromDependabot(":instrumentation:apache-dubbo-2.7:javaagent") hideFromDependabot(":instrumentation:apache-dubbo-2.7:library-autoconfigure") hideFromDependabot(":instrumentation:apache-dubbo-2.7:testing") hideFromDependabot(":instrumentation:apache-httpasyncclient-4.1:javaagent") +*/ hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-2.0:javaagent") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-4.3:library") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-4.3:testing") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-5.0:javaagent") +/* hideFromDependabot(":instrumentation:armeria-1.3:javaagent") hideFromDependabot(":instrumentation:armeria-1.3:library") hideFromDependabot(":instrumentation:armeria-1.3:testing") hideFromDependabot(":instrumentation:async-http-client:async-http-client-1.9:javaagent") hideFromDependabot(":instrumentation:async-http-client:async-http-client-2.0:javaagent") +*/ hideFromDependabot(":instrumentation:aws-lambda:aws-lambda-core-1.0:javaagent") hideFromDependabot(":instrumentation:aws-lambda:aws-lambda-core-1.0:library") hideFromDependabot(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing") @@ -166,6 +171,7 @@ hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:javaagent") hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:library") hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:library-autoconfigure") hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:testing") +/* hideFromDependabot(":instrumentation:azure-core:azure-core-1.14:javaagent") hideFromDependabot(":instrumentation:azure-core:azure-core-1.14:library-instrumentation-shaded") hideFromDependabot(":instrumentation:azure-core:azure-core-1.19:javaagent") @@ -184,6 +190,7 @@ hideFromDependabot(":instrumentation:cdi-testing") hideFromDependabot(":instrumentation:graphql-java-12.0:javaagent") hideFromDependabot(":instrumentation:graphql-java-12.0:library") hideFromDependabot(":instrumentation:graphql-java-12.0:testing") +*/ hideFromDependabot(":instrumentation:internal:internal-application-logger:bootstrap") hideFromDependabot(":instrumentation:internal:internal-application-logger:javaagent") hideFromDependabot(":instrumentation:internal:internal-class-loader:javaagent") @@ -195,6 +202,7 @@ hideFromDependabot(":instrumentation:internal:internal-reflection:javaagent") hideFromDependabot(":instrumentation:internal:internal-reflection:javaagent-integration-tests") hideFromDependabot(":instrumentation:internal:internal-url-class-loader:javaagent") hideFromDependabot(":instrumentation:internal:internal-url-class-loader:javaagent-integration-tests") +/* hideFromDependabot(":instrumentation:c3p0-0.9:javaagent") hideFromDependabot(":instrumentation:c3p0-0.9:library") hideFromDependabot(":instrumentation:c3p0-0.9:testing") @@ -223,11 +231,13 @@ hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-commo hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-5.0:javaagent") hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-5.3:javaagent") hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-6.0:javaagent") +*/ hideFromDependabot(":instrumentation:executors:bootstrap") hideFromDependabot(":instrumentation:executors:javaagent") hideFromDependabot(":instrumentation:executors:testing") hideFromDependabot(":instrumentation:external-annotations:javaagent") hideFromDependabot(":instrumentation:external-annotations:javaagent-unit-tests") +/* hideFromDependabot(":instrumentation:finatra-2.9:javaagent") hideFromDependabot(":instrumentation:geode-1.4:javaagent") hideFromDependabot(":instrumentation:google-http-client-1.19:javaagent") @@ -366,6 +376,7 @@ hideFromDependabot(":instrumentation:mongo:mongo-3.7:javaagent") hideFromDependabot(":instrumentation:mongo:mongo-4.0:javaagent") hideFromDependabot(":instrumentation:mongo:mongo-async-3.3:javaagent") hideFromDependabot(":instrumentation:mongo:mongo-common:testing") +*/ hideFromDependabot(":instrumentation:netty:netty-3.8:javaagent") hideFromDependabot(":instrumentation:netty:netty-4.0:javaagent") hideFromDependabot(":instrumentation:netty:netty-4.1:javaagent") @@ -374,11 +385,12 @@ hideFromDependabot(":instrumentation:netty:netty-4.1:testing") hideFromDependabot(":instrumentation:netty:netty-4-common:javaagent") hideFromDependabot(":instrumentation:netty:netty-4-common:library") hideFromDependabot(":instrumentation:netty:netty-common:library") +/* hideFromDependabot(":instrumentation:okhttp:okhttp-2.2:javaagent") hideFromDependabot(":instrumentation:okhttp:okhttp-3.0:javaagent") hideFromDependabot(":instrumentation:okhttp:okhttp-3.0:library") hideFromDependabot(":instrumentation:okhttp:okhttp-3.0:testing") -hideFromDependabot(":instrumentation:opencensus-shim:testing") +*/ hideFromDependabot(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent") hideFromDependabot(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent") hideFromDependabot(":instrumentation:opentelemetry-api:opentelemetry-api-1.10:javaagent") @@ -389,13 +401,13 @@ hideFromDependabot(":instrumentation:opentelemetry-extension-kotlin-1.0:javaagen hideFromDependabot(":instrumentation:opentelemetry-instrumentation-annotations-1.16:javaagent") hideFromDependabot(":instrumentation:opentelemetry-instrumentation-api:javaagent") hideFromDependabot(":instrumentation:opentelemetry-instrumentation-api:testing") +/* hideFromDependabot(":instrumentation:oracle-ucp-11.2:javaagent") hideFromDependabot(":instrumentation:oracle-ucp-11.2:library") hideFromDependabot(":instrumentation:oracle-ucp-11.2:testing") hideFromDependabot(":instrumentation:oshi:javaagent") hideFromDependabot(":instrumentation:oshi:library") hideFromDependabot(":instrumentation:oshi:testing") -hideFromDependabot(":instrumentation:payara:javaagent") hideFromDependabot(":instrumentation:play:play-mvc:play-mvc-2.4:javaagent") hideFromDependabot(":instrumentation:play:play-mvc:play-mvc-2.6:javaagent") hideFromDependabot(":instrumentation:play:play-ws:play-ws-1.0:javaagent") @@ -457,10 +469,6 @@ hideFromDependabot(":instrumentation:rxjava:rxjava-3.1.1:library") hideFromDependabot(":instrumentation:rxjava:rxjava-3.1.1:javaagent") hideFromDependabot(":instrumentation:rxjava:rxjava-3-common:library") hideFromDependabot(":instrumentation:rxjava:rxjava-3-common:testing") -hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:javaagent") -hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:common-testing") -hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:quarkus2-testing") -hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:quarkus3-testing") hideFromDependabot(":instrumentation:scala-fork-join-2.8:javaagent") hideFromDependabot(":instrumentation:servlet:servlet-common:bootstrap") hideFromDependabot(":instrumentation:servlet:servlet-common:javaagent") @@ -536,10 +544,13 @@ hideFromDependabot(":instrumentation:vibur-dbcp-11.0:library") hideFromDependabot(":instrumentation:vibur-dbcp-11.0:testing") hideFromDependabot(":instrumentation:wicket-8.0:javaagent") hideFromDependabot(":instrumentation:zio:zio-2.0:javaagent") +*/ +/* // benchmark include(":benchmark-overhead-jmh") include(":benchmark-jfr-analyzer") +*/ // this effectively hides the submodule from dependabot because dependabot only regex parses gradle // files looking for certain patterns From 4b910775d7310e4a5de11359774e297b0029348b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Tue, 4 Jul 2023 17:56:09 +0200 Subject: [PATCH 3/6] v1: Replace Sqs*Access classes. --- .../aws-sdk-1.11/javaagent/build.gradle.kts | 2 - .../awssdk/v1_11/SqsAccess.java | 15 ++- .../instrumentation/awssdk/v1_11/SqsImpl.java | 51 +++++++++- .../awssdk/v1_11/SqsMessageAccess.java | 63 ------------ .../v1_11/SqsReceiveMessageRequestAccess.java | 99 ------------------- .../v1_11/SqsReceiveMessageResultAccess.java | 64 ------------ .../awssdk/v1_11/TracingRequestHandler.java | 31 +----- settings.gradle.kts | 25 ++--- 8 files changed, 72 insertions(+), 278 deletions(-) delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsMessageAccess.java delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageRequestAccess.java delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageResultAccess.java diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts index f4b40b6922d5..e04a0ce1b5a0 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts +++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/build.gradle.kts @@ -19,7 +19,6 @@ muzzle { excludeInstrumentationName("aws-sdk-1.11-sqs") } - fail { group.set("com.amazonaws") module.set("aws-java-sdk-core") @@ -33,7 +32,6 @@ muzzle { module.set("aws-java-sdk-sqs") versions.set("[1.10.33,)") } - } dependencies { diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java index d4a4995c7f80..12fe4bae8d67 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsAccess.java @@ -6,6 +6,9 @@ package io.opentelemetry.instrumentation.awssdk.v1_11; import com.amazonaws.AmazonWebServiceRequest; +import com.amazonaws.Request; +import com.amazonaws.Response; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle; final class SqsAccess { @@ -14,7 +17,15 @@ private SqsAccess() {} private static final boolean enabled = PluginImplUtil.isImplPresent("SqsImpl"); @NoMuzzle - public static boolean isReceiveMessageRequest(AmazonWebServiceRequest originalRequest) { - return enabled && SqsImpl.isReceiveMessageRequest(originalRequest); + static boolean afterResponse( + Request request, + Response response, + Instrumenter, Response> consumerInstrumenter) { + return enabled && SqsImpl.afterResponse(request, response, consumerInstrumenter); + } + + @NoMuzzle + static boolean beforeMarshalling(AmazonWebServiceRequest request) { + return enabled && SqsImpl.beforeMarshalling(request); } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java index 4f2f1c929222..a0e32e7732e8 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java @@ -6,12 +6,18 @@ package io.opentelemetry.instrumentation.awssdk.v1_11; import com.amazonaws.AmazonWebServiceRequest; +import com.amazonaws.Request; +import com.amazonaws.Response; import com.amazonaws.services.sqs.AmazonSQS; +import com.amazonaws.services.sqs.model.Message; import com.amazonaws.services.sqs.model.ReceiveMessageRequest; +import com.amazonaws.services.sqs.model.ReceiveMessageResult; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; final class SqsImpl { static { - // Force loading of SqsClient; this ensures that an exception is thrown at this point when the + // Force loading of SQS class; this ensures that an exception is thrown at this point when the // SQS library is not present, which will cause SqsAccess to have enabled=false in library mode. @SuppressWarnings("unused") String ensureLoadedDummy = AmazonSQS.class.getName(); @@ -19,7 +25,46 @@ final class SqsImpl { private SqsImpl() {} - public static boolean isReceiveMessageRequest(AmazonWebServiceRequest originalRequest) { - return originalRequest instanceof ReceiveMessageRequest; + public static boolean afterResponse( + Request request, + Response response, + Instrumenter, Response> consumerInstrumenter) { + if (response.getAwsResponse() instanceof ReceiveMessageResult) { + afterConsumerResponse(request, response, consumerInstrumenter); + return true; + } + return false; + } + + /** Create and close CONSUMER span for each message consumed. */ + private static void afterConsumerResponse( + Request request, + Response response, + Instrumenter, Response> consumerInstrumenter) { + ReceiveMessageResult receiveMessageResult = (ReceiveMessageResult) response.getAwsResponse(); + for (Message message : receiveMessageResult.getMessages()) { + createConsumerSpan(message, request, response, consumerInstrumenter); + } + } + + private static void createConsumerSpan( + Message message, + Request request, + Response response, + Instrumenter, Response> consumerInstrumenter) { + Context parentContext = SqsParentContext.ofSystemAttributes(message.getAttributes()); + Context context = consumerInstrumenter.start(parentContext, request); + consumerInstrumenter.end(context, request, response, null); + } + + static boolean beforeMarshalling(AmazonWebServiceRequest rawRequest) { + if (rawRequest instanceof ReceiveMessageRequest) { + ReceiveMessageRequest request = (ReceiveMessageRequest) rawRequest; + if (!request.getAttributeNames().contains(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE)) { + request.withAttributeNames(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE); + } + return true; + } + return false; } } diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsMessageAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsMessageAccess.java deleted file mode 100644 index 84726bab934f..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsMessageAccess.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v1_11; - -import static java.lang.invoke.MethodType.methodType; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Collections; -import java.util.Map; -import javax.annotation.Nullable; - -/** - * Reflective access to aws-sdk-java-sqs class Message. - * - *

We currently don't have a good pattern of instrumenting a core library with various plugins - * that need plugin-specific instrumentation - if we accessed the class directly, Muzzle would - * prevent the entire instrumentation from loading when the plugin isn't available. We need to - * carefully check this class has all reflection errors result in no-op, and in the future we will - * hopefully come up with a better pattern. - */ -final class SqsMessageAccess { - - @Nullable private static final MethodHandle GET_ATTRIBUTES; - - static { - Class messageClass = null; - try { - messageClass = Class.forName("com.amazonaws.services.sqs.model.Message"); - } catch (Throwable t) { - // Ignore. - } - if (messageClass != null) { - MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - MethodHandle getAttributes = null; - try { - getAttributes = lookup.findVirtual(messageClass, "getAttributes", methodType(Map.class)); - } catch (NoSuchMethodException | IllegalAccessException e) { - // Ignore - } - GET_ATTRIBUTES = getAttributes; - } else { - GET_ATTRIBUTES = null; - } - } - - @SuppressWarnings("unchecked") - static Map getAttributes(Object message) { - if (GET_ATTRIBUTES == null) { - return Collections.emptyMap(); - } - try { - return (Map) GET_ATTRIBUTES.invoke(message); - } catch (Throwable t) { - return Collections.emptyMap(); - } - } - - private SqsMessageAccess() {} -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageRequestAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageRequestAccess.java deleted file mode 100644 index 122e66f8c0d3..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageRequestAccess.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v1_11; - -import static java.lang.invoke.MethodType.methodType; - -import com.amazonaws.AmazonWebServiceRequest; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; - -/** - * Reflective access to aws-sdk-java-sqs class ReceiveMessageRequest. - * - *

We currently don't have a good pattern of instrumenting a core library with various plugins - * that need plugin-specific instrumentation - if we accessed the class directly, Muzzle would - * prevent the entire instrumentation from loading when the plugin isn't available. We need to - * carefully check this class has all reflection errors result in no-op, and in the future we will - * hopefully come up with a better pattern. - */ -final class SqsReceiveMessageRequestAccess { - - @Nullable private static final MethodHandle WITH_ATTRIBUTE_NAMES; - @Nullable private static final MethodHandle GET_ATTRIBUTE_NAMES; - - static { - Class receiveMessageRequestClass = null; - try { - receiveMessageRequestClass = - Class.forName("com.amazonaws.services.sqs.model.ReceiveMessageRequest"); - } catch (Throwable t) { - // Ignore. - } - if (receiveMessageRequestClass != null) { - MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - MethodHandle withAttributeNames = null; - try { - withAttributeNames = - lookup.findVirtual( - receiveMessageRequestClass, - "withAttributeNames", - methodType(receiveMessageRequestClass, String[].class)); - } catch (NoSuchMethodException | IllegalAccessException e) { - // Ignore - } - WITH_ATTRIBUTE_NAMES = withAttributeNames; - - MethodHandle getAttributeNames = null; - try { - getAttributeNames = - lookup.findVirtual( - receiveMessageRequestClass, "getAttributeNames", methodType(List.class)); - } catch (NoSuchMethodException | IllegalAccessException e) { - // Ignore - } - GET_ATTRIBUTE_NAMES = getAttributeNames; - } else { - WITH_ATTRIBUTE_NAMES = null; - GET_ATTRIBUTE_NAMES = null; - } - } - - static boolean isInstance(AmazonWebServiceRequest request) { - return request - .getClass() - .getName() - .equals("com.amazonaws.services.sqs.model.ReceiveMessageRequest"); - } - - static void withAttributeNames(AmazonWebServiceRequest request, String name) { - if (WITH_ATTRIBUTE_NAMES == null) { - return; - } - try { - WITH_ATTRIBUTE_NAMES.invoke(request, name); - } catch (Throwable throwable) { - // Ignore - } - } - - @SuppressWarnings("unchecked") - static List getAttributeNames(AmazonWebServiceRequest request) { - if (GET_ATTRIBUTE_NAMES == null) { - return Collections.emptyList(); - } - try { - return (List) GET_ATTRIBUTE_NAMES.invoke(request); - } catch (Throwable t) { - return Collections.emptyList(); - } - } - - private SqsReceiveMessageRequestAccess() {} -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageResultAccess.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageResultAccess.java deleted file mode 100644 index 27fb6e255f92..000000000000 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsReceiveMessageResultAccess.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.instrumentation.awssdk.v1_11; - -import static java.lang.invoke.MethodType.methodType; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nullable; - -/** - * Reflective access to aws-sdk-java-sqs class ReceiveMessageResult. - * - *

We currently don't have a good pattern of instrumenting a core library with various plugins - * that need plugin-specific instrumentation - if we accessed the class directly, Muzzle would - * prevent the entire instrumentation from loading when the plugin isn't available. We need to - * carefully check this class has all reflection errors result in no-op, and in the future we will - * hopefully come up with a better pattern. - */ -final class SqsReceiveMessageResultAccess { - - @Nullable private static final MethodHandle GET_MESSAGES; - - static { - Class receiveMessageResultClass = null; - try { - receiveMessageResultClass = - Class.forName("com.amazonaws.services.sqs.model.ReceiveMessageResult"); - } catch (Throwable t) { - // Ignore. - } - if (receiveMessageResultClass != null) { - MethodHandles.Lookup lookup = MethodHandles.publicLookup(); - MethodHandle getMessages = null; - try { - getMessages = - lookup.findVirtual(receiveMessageResultClass, "getMessages", methodType(List.class)); - } catch (NoSuchMethodException | IllegalAccessException e) { - // Ignore - } - GET_MESSAGES = getMessages; - } else { - GET_MESSAGES = null; - } - } - - static List getMessages(Object result) { - if (GET_MESSAGES == null) { - return Collections.emptyList(); - } - try { - return (List) GET_MESSAGES.invoke(result); - } catch (Throwable t) { - return Collections.emptyList(); - } - } - - private SqsReceiveMessageResultAccess() {} -} diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java index e15f4cfb5725..11d2f3a6fed3 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/TracingRequestHandler.java @@ -14,7 +14,6 @@ import io.opentelemetry.context.Context; import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; -import java.util.List; import javax.annotation.Nullable; /** Tracing Request Handler. */ @@ -58,40 +57,18 @@ public void beforeRequest(Request request) { @Override @CanIgnoreReturnValue public AmazonWebServiceRequest beforeMarshalling(AmazonWebServiceRequest request) { - if (SqsReceiveMessageRequestAccess.isInstance(request)) { - if (!SqsReceiveMessageRequestAccess.getAttributeNames(request) - .contains(SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE)) { - SqsReceiveMessageRequestAccess.withAttributeNames( - request, SqsParentContext.AWS_TRACE_SYSTEM_ATTRIBUTE); - } - } + // TODO: We are modifying the request in-place instead of using clone() as recommended + // by the Javadoc in the interface. + SqsAccess.beforeMarshalling(request); return request; } @Override public void afterResponse(Request request, Response response) { - if (SqsAccess.isReceiveMessageRequest(request.getOriginalRequest())) { - afterConsumerResponse(request, response); - } + SqsAccess.afterResponse(request, response, consumerInstrumenter); finish(request, response, null); } - /** Create and close CONSUMER span for each message consumed. */ - private void afterConsumerResponse(Request request, Response response) { - Object receiveMessageResult = response.getAwsResponse(); - List messages = SqsReceiveMessageResultAccess.getMessages(receiveMessageResult); - for (Object message : messages) { - createConsumerSpan(message, request, response); - } - } - - private void createConsumerSpan(Object message, Request request, Response response) { - Context parentContext = - SqsParentContext.ofSystemAttributes(SqsMessageAccess.getAttributes(message)); - Context context = consumerInstrumenter.start(parentContext, request); - consumerInstrumenter.end(context, request, response, null); - } - @Override public void afterError(Request request, Response response, Exception e) { finish(request, response, e); diff --git a/settings.gradle.kts b/settings.gradle.kts index 4c03e2759be9..cdb637ca3426 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -120,7 +120,6 @@ include(":testing-common") include(":testing-common:integration-tests") include(":testing-common:library-for-integration-tests") -/* // smoke tests include(":smoke-tests") include(":smoke-tests:images:fake-backend") @@ -132,8 +131,7 @@ include(":smoke-tests:images:servlet") hideFromDependabot(":smoke-tests:images:servlet:servlet-3.0") hideFromDependabot(":smoke-tests:images:servlet:servlet-5.0") hideFromDependabot(":smoke-tests:images:spring-boot") -*/ -/* + hideFromDependabot("instrumentation:akka:akka-actor-2.3:javaagent") hideFromDependabot(":instrumentation:akka:akka-actor-fork-join-2.5:javaagent") hideFromDependabot(":instrumentation:akka:akka-http-10.0:javaagent") @@ -144,19 +142,16 @@ hideFromDependabot(":instrumentation:apache-dubbo-2.7:javaagent") hideFromDependabot(":instrumentation:apache-dubbo-2.7:library-autoconfigure") hideFromDependabot(":instrumentation:apache-dubbo-2.7:testing") hideFromDependabot(":instrumentation:apache-httpasyncclient-4.1:javaagent") -*/ hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-2.0:javaagent") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-4.0:javaagent") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-4.3:library") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-4.3:testing") hideFromDependabot(":instrumentation:apache-httpclient:apache-httpclient-5.0:javaagent") -/* hideFromDependabot(":instrumentation:armeria-1.3:javaagent") hideFromDependabot(":instrumentation:armeria-1.3:library") hideFromDependabot(":instrumentation:armeria-1.3:testing") hideFromDependabot(":instrumentation:async-http-client:async-http-client-1.9:javaagent") hideFromDependabot(":instrumentation:async-http-client:async-http-client-2.0:javaagent") -*/ hideFromDependabot(":instrumentation:aws-lambda:aws-lambda-core-1.0:javaagent") hideFromDependabot(":instrumentation:aws-lambda:aws-lambda-core-1.0:library") hideFromDependabot(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing") @@ -171,7 +166,6 @@ hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:javaagent") hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:library") hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:library-autoconfigure") hideFromDependabot(":instrumentation:aws-sdk:aws-sdk-2.2:testing") -/* hideFromDependabot(":instrumentation:azure-core:azure-core-1.14:javaagent") hideFromDependabot(":instrumentation:azure-core:azure-core-1.14:library-instrumentation-shaded") hideFromDependabot(":instrumentation:azure-core:azure-core-1.19:javaagent") @@ -190,7 +184,6 @@ hideFromDependabot(":instrumentation:cdi-testing") hideFromDependabot(":instrumentation:graphql-java-12.0:javaagent") hideFromDependabot(":instrumentation:graphql-java-12.0:library") hideFromDependabot(":instrumentation:graphql-java-12.0:testing") -*/ hideFromDependabot(":instrumentation:internal:internal-application-logger:bootstrap") hideFromDependabot(":instrumentation:internal:internal-application-logger:javaagent") hideFromDependabot(":instrumentation:internal:internal-class-loader:javaagent") @@ -202,7 +195,6 @@ hideFromDependabot(":instrumentation:internal:internal-reflection:javaagent") hideFromDependabot(":instrumentation:internal:internal-reflection:javaagent-integration-tests") hideFromDependabot(":instrumentation:internal:internal-url-class-loader:javaagent") hideFromDependabot(":instrumentation:internal:internal-url-class-loader:javaagent-integration-tests") -/* hideFromDependabot(":instrumentation:c3p0-0.9:javaagent") hideFromDependabot(":instrumentation:c3p0-0.9:library") hideFromDependabot(":instrumentation:c3p0-0.9:testing") @@ -231,13 +223,11 @@ hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-commo hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-5.0:javaagent") hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-5.3:javaagent") hideFromDependabot(":instrumentation:elasticsearch:elasticsearch-transport-6.0:javaagent") -*/ hideFromDependabot(":instrumentation:executors:bootstrap") hideFromDependabot(":instrumentation:executors:javaagent") hideFromDependabot(":instrumentation:executors:testing") hideFromDependabot(":instrumentation:external-annotations:javaagent") hideFromDependabot(":instrumentation:external-annotations:javaagent-unit-tests") -/* hideFromDependabot(":instrumentation:finatra-2.9:javaagent") hideFromDependabot(":instrumentation:geode-1.4:javaagent") hideFromDependabot(":instrumentation:google-http-client-1.19:javaagent") @@ -376,7 +366,6 @@ hideFromDependabot(":instrumentation:mongo:mongo-3.7:javaagent") hideFromDependabot(":instrumentation:mongo:mongo-4.0:javaagent") hideFromDependabot(":instrumentation:mongo:mongo-async-3.3:javaagent") hideFromDependabot(":instrumentation:mongo:mongo-common:testing") -*/ hideFromDependabot(":instrumentation:netty:netty-3.8:javaagent") hideFromDependabot(":instrumentation:netty:netty-4.0:javaagent") hideFromDependabot(":instrumentation:netty:netty-4.1:javaagent") @@ -385,12 +374,11 @@ hideFromDependabot(":instrumentation:netty:netty-4.1:testing") hideFromDependabot(":instrumentation:netty:netty-4-common:javaagent") hideFromDependabot(":instrumentation:netty:netty-4-common:library") hideFromDependabot(":instrumentation:netty:netty-common:library") -/* hideFromDependabot(":instrumentation:okhttp:okhttp-2.2:javaagent") hideFromDependabot(":instrumentation:okhttp:okhttp-3.0:javaagent") hideFromDependabot(":instrumentation:okhttp:okhttp-3.0:library") hideFromDependabot(":instrumentation:okhttp:okhttp-3.0:testing") -*/ +hideFromDependabot(":instrumentation:opencensus-shim:testing") hideFromDependabot(":instrumentation:opentelemetry-api:opentelemetry-api-1.0:javaagent") hideFromDependabot(":instrumentation:opentelemetry-api:opentelemetry-api-1.4:javaagent") hideFromDependabot(":instrumentation:opentelemetry-api:opentelemetry-api-1.10:javaagent") @@ -401,13 +389,13 @@ hideFromDependabot(":instrumentation:opentelemetry-extension-kotlin-1.0:javaagen hideFromDependabot(":instrumentation:opentelemetry-instrumentation-annotations-1.16:javaagent") hideFromDependabot(":instrumentation:opentelemetry-instrumentation-api:javaagent") hideFromDependabot(":instrumentation:opentelemetry-instrumentation-api:testing") -/* hideFromDependabot(":instrumentation:oracle-ucp-11.2:javaagent") hideFromDependabot(":instrumentation:oracle-ucp-11.2:library") hideFromDependabot(":instrumentation:oracle-ucp-11.2:testing") hideFromDependabot(":instrumentation:oshi:javaagent") hideFromDependabot(":instrumentation:oshi:library") hideFromDependabot(":instrumentation:oshi:testing") +hideFromDependabot(":instrumentation:payara:javaagent") hideFromDependabot(":instrumentation:play:play-mvc:play-mvc-2.4:javaagent") hideFromDependabot(":instrumentation:play:play-mvc:play-mvc-2.6:javaagent") hideFromDependabot(":instrumentation:play:play-ws:play-ws-1.0:javaagent") @@ -469,6 +457,10 @@ hideFromDependabot(":instrumentation:rxjava:rxjava-3.1.1:library") hideFromDependabot(":instrumentation:rxjava:rxjava-3.1.1:javaagent") hideFromDependabot(":instrumentation:rxjava:rxjava-3-common:library") hideFromDependabot(":instrumentation:rxjava:rxjava-3-common:testing") +hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:javaagent") +hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:common-testing") +hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:quarkus2-testing") +hideFromDependabot(":instrumentation:quarkus-resteasy-reactive:quarkus3-testing") hideFromDependabot(":instrumentation:scala-fork-join-2.8:javaagent") hideFromDependabot(":instrumentation:servlet:servlet-common:bootstrap") hideFromDependabot(":instrumentation:servlet:servlet-common:javaagent") @@ -544,13 +536,10 @@ hideFromDependabot(":instrumentation:vibur-dbcp-11.0:library") hideFromDependabot(":instrumentation:vibur-dbcp-11.0:testing") hideFromDependabot(":instrumentation:wicket-8.0:javaagent") hideFromDependabot(":instrumentation:zio:zio-2.0:javaagent") -*/ -/* // benchmark include(":benchmark-overhead-jmh") include(":benchmark-jfr-analyzer") -*/ // this effectively hides the submodule from dependabot because dependabot only regex parses gradle // files looking for certain patterns From 4aea25730d1f5787751a812675433224af02a61f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 5 Jul 2023 09:10:44 +0200 Subject: [PATCH 4/6] Trigger build. From 5ed58d9da5525c938a5986edd7c8d776f4d696df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Wed, 5 Jul 2023 09:49:32 +0200 Subject: [PATCH 5/6] Dont mark method in package-private class public Co-authored-by: Mateusz Rzeszutek --- .../io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java index a0e32e7732e8..f4cd92757999 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SqsImpl.java @@ -25,7 +25,7 @@ final class SqsImpl { private SqsImpl() {} - public static boolean afterResponse( + static boolean afterResponse( Request request, Response response, Instrumenter, Response> consumerInstrumenter) { From c2cb01d6c6df79385ed85215ff8c88d56b758c03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Neum=C3=BCller?= Date: Thu, 6 Jul 2023 10:59:01 +0200 Subject: [PATCH 6/6] Clean up comment & log message. --- .../awssdk/v1_11/PluginImplUtil.java | 27 ++++++++++------- .../awssdk/v2_2/PluginImplUtil.java | 29 ++++++++++++------- 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java index d16ce1983efc..364bfffe5318 100644 --- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java +++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/PluginImplUtil.java @@ -16,33 +16,40 @@ private PluginImplUtil() {} /** * Check if the given {@code moduleNameImpl} is present. * - *

For library instrumentations, the Impls will always be available but might fail to load if - * the corresponding SDK classes are not on the class path. For javaagent, the Impl is available - * only when the corresponding InstrumentationModule was successfully applied (muzzle passed). + *

For library instrumentations, the Impls will always be available but might fail to + * load/link/initialize if the corresponding SDK classes are not on the class path. For javaagent, + * the Impl is available only when the corresponding InstrumentationModule was successfully + * applied (muzzle passed). * - *

Note that an present-but-incompatible library can only be detected by Muzzle. In + *

Note that an present-but-incompatible library can only be reliably detected by Muzzle. In * library-mode, users need to ensure they are using a compatible SDK (component) versions * themselves. * * @param implSimpleClassName The simple name of the impl class, e.g. {@code "SqsImpl"}. * */ static boolean isImplPresent(String implSimpleClassName) { + // Computing the full name dynamically name here because library instrumentation classes are + // relocated when embedded in the agent. // We use getName().replace() instead of getPackage() because the latter is not guaranteed to // work in all cases (e.g., we might be loaded into a custom classloader that doesn't handle it) String implFullClassName = PluginImplUtil.class.getName().replace(".PluginImplUtil", "." + implSimpleClassName); try { - // using package name here because library instrumentation classes are relocated when embedded - // in the agent Class.forName(implFullClassName); return true; } catch (ClassNotFoundException | LinkageError e) { // ClassNotFoundException will happen when muzzle disabled us in javaagent mode; LinkageError - // (most likely NoClassDefFoundError) should happen when the class is loaded in library mode - // (where it is always available) but a dependency failed to load (most likely because the - // corresponding SDK dependency is not on the class path). + // (most likely a NoClassDefFoundError, potentially wrapped in an ExceptionInInitializerError) + // should be thrown when the class is loaded in library mode (where the Impl class itself can + // always be found) but a dependency failed to load (most likely because the corresponding SDK + // dependency is not on the class path). logger.log( - Level.FINE, e, () -> implFullClassName + " not present, probably incompatible version"); + Level.FINE, + e, + () -> + implFullClassName + + " not present. " + + "Most likely, corresponding SDK component is either not on classpath or incompatible."); return false; } } diff --git a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/PluginImplUtil.java b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/PluginImplUtil.java index f5043ae13257..3ba1611a541e 100644 --- a/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/PluginImplUtil.java +++ b/instrumentation/aws-sdk/aws-sdk-2.2/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/PluginImplUtil.java @@ -8,7 +8,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -final class PluginImplUtil { +final class PluginImplUtil { // TODO: Copy & pasted to v1 private PluginImplUtil() {} private static final Logger logger = Logger.getLogger(PluginImplUtil.class.getName()); @@ -16,33 +16,40 @@ private PluginImplUtil() {} /** * Check if the given {@code moduleNameImpl} is present. * - *

For library instrumentations, the Impls will always be available but might fail to load if - * the corresponding SDK classes are not on the class path. For javaagent, the Impl is available - * only when the corresponding InstrumentationModule was successfully applied (muzzle passed). + *

For library instrumentations, the Impls will always be available but might fail to + * load/link/initialize if the corresponding SDK classes are not on the class path. For javaagent, + * the Impl is available only when the corresponding InstrumentationModule was successfully + * applied (muzzle passed). * - *

Note that an present-but-incompatible library can only be detected by Muzzle. In + *

Note that an present-but-incompatible library can only be reliably detected by Muzzle. In * library-mode, users need to ensure they are using a compatible SDK (component) versions * themselves. * * @param implSimpleClassName The simple name of the impl class, e.g. {@code "SqsImpl"}. * */ static boolean isImplPresent(String implSimpleClassName) { + // Computing the full name dynamically name here because library instrumentation classes are + // relocated when embedded in the agent. // We use getName().replace() instead of getPackage() because the latter is not guaranteed to // work in all cases (e.g., we might be loaded into a custom classloader that doesn't handle it) String implFullClassName = PluginImplUtil.class.getName().replace(".PluginImplUtil", "." + implSimpleClassName); try { - // using package name here because library instrumentation classes are relocated when embedded - // in the agent Class.forName(implFullClassName); return true; } catch (ClassNotFoundException | LinkageError e) { // ClassNotFoundException will happen when muzzle disabled us in javaagent mode; LinkageError - // (most likely NoClassDefFoundError) should happen when the class is loaded in library mode - // (where it is always available) but a dependency failed to load (most likely because the - // corresponding SDK dependency is not on the class path). + // (most likely a NoClassDefFoundError, potentially wrapped in an ExceptionInInitializerError) + // should be thrown when the class is loaded in library mode (where the Impl class itself can + // always be found) but a dependency failed to load (most likely because the corresponding SDK + // dependency is not on the class path). logger.log( - Level.FINE, e, () -> implFullClassName + " not present, probably incompatible version"); + Level.FINE, + e, + () -> + implFullClassName + + " not present. " + + "Most likely, corresponding SDK component is either not on classpath or incompatible."); return false; } }