open-telemetry / opentelemetry-java-instrumentation

OpenTelemetry auto-instrumentation and instrumentation libraries for Java

Home Page:https://opentelemetry.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

add support for graalvm link-at-build to aws_v2_2 instrumentation

scrocquesel opened this issue · comments

Is your feature request related to a problem? Please describe.

Quarkus in native build use --link-at-build to require all classes to be fully linked at build time. The aws instrumentation has optional dependency on SQS and SNS package. Usually, GraalVM substitution helps in removing code to unreachable classes.

For SNS, something like the following should work

public class OtelSubstitutions {

    static final String SOFTWARE_AMAZON_AWSSDK_SNS_PACKAGE = "software.amazon.awssdk.services.sns";

    static final class IsSnsAbsent implements BooleanSupplier {
        @Override
        public boolean getAsBoolean() {
            return !Arrays.asList(Package.getPackages()).stream()
                    .map(p -> p.getName())
                    .anyMatch(p -> p.equals(SOFTWARE_AMAZON_AWSSDK_SNS_PACKAGE));
        }
    }

    @TargetClass(className = "io.opentelemetry.instrumentation.awssdk.v2_2.SnsImpl", onlyWith = IsSnsAbsent.class)
    @Delete
    final class Delete_SnsImpl {
    }

    @TargetClass(className = "io.opentelemetry.instrumentation.awssdk.v2_2.SnsAccess", onlyWith = IsSnsAbsent.class)
    @Delete
    final class Target_SnsAccess {

        @Delete
        private static final boolean enabled = false;

        @Substitute
        public static SdkRequest modifyRequest(
                SdkRequest request, io.opentelemetry.context.Context otelContext,
                TextMapPropagator messagingPropagator) {
            return null;
        }
    }
}

For SQS, we could substitute SqSAccess, but it is not enough because classes from SQS dependency are a lot more intricated in the interceptor and factory.
While there are already abstractions in place to mitigate potential issues, they are insufficient.

For example, TracingList exposes software.amazon.awssdk.services.sqs.model.Message, which GraalVM will report as undefined because TracingList is exposed and utilized by TracingExecutionInterceptor. Removing the class and the field is a potential solution, but it requires rewriting the clearAttributes method in the substitute just to remove the last line.
The TRACING_MESSAGES_ATTRIBUTE and it's clear call may be relocated in the SqsAccess class to facilitate easier nooping.
Note that I can't find any usage of TRACING_MESSAGES_ATTRIBUTE but the clear call, it may not be necessary at all.

Another example is SqsMessage, which exposes software.amazon.awssdk.services.sqs.model.MessageAttributeValue. SqsMessage is the exposed by SqsProcessRequest and SqsReceiveRequest, both use in the TracingExecutionInterceptor and AwsSdkInstrumenterFactory.

Describe the solution you'd like

Ensure compatibility for compilation with native GraalVM using --link-at-build time without dependencies on SQS or SNS. No substitutions need to be provided, but, for SQS, they should be easily implementable like for SnsAccess.

If TRACING_MESSAGES_ATTRIBUTE is not necessary and removed, I guess a deep abstraction of SqsMessage should be enough.

Describe alternatives you've considered

No response

Additional context

No response

@scrocquesel It seems you are using Quarkus native with the AWS SDK?

cc @brunobat

@scrocquesel It seems you are using Quarkus native with the AWS SDK?

cc @brunobat

Actually, I'm a maintainer of https://github.com/quarkiverse/quarkus-amazon-services. I come up with these substitutions

https://github.com/quarkiverse/quarkus-amazon-services/pull/1242/files#diff-1315d92c76bc1b2c96ba5966b4dca0e048aa0c6b92c4f6d7531b15542a9d52c7

The pattern implemented in SqsAccess and SnsAccess proved to be very helpful, and some method or class substitutions are ultimately unnecessary because there are no existing code paths utilizing them. For SQS, it appears that only substituting AwsSdkInstrumenterFactory::consumerProcessInstrumenter, in addition to the centralized SqsAccess class, is required because it loads software.amazon.awssdk.services.sqs.model.MessageAttributeValue via SqsParentContext$MessageAttributeValueMapGetter.
Shouldn't it be something that Muzzle would have report ?

However, I'm concerned about the fragility of my code and how it might be affected by future changes.