Skip to content

Commit d6e8441

Browse files
committed
Use NoMuzzle annotation instead of using reflection to avoid Muzzle check
1 parent 0935bd0 commit d6e8441

File tree

1 file changed

+41
-83
lines changed

1 file changed

+41
-83
lines changed

lambda-layer/patches/opentelemetry-java-instrumentation.patch

Lines changed: 41 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ index a6b89d253d..e62d30eddb 100644
2525
if (!functionInstrumenter().shouldStart(parentContext, otelInput)) {
2626
return;
2727
diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/build.gradle.kts b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/build.gradle.kts
28-
index df605add2f..b2f01d9d4d 100644
28+
index df605add2f..e16c736990 100644
2929
--- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/build.gradle.kts
3030
+++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/build.gradle.kts
31-
@@ -9,7 +9,7 @@ dependencies {
31+
@@ -5,11 +5,12 @@ plugins {
32+
dependencies {
33+
compileOnly("io.opentelemetry:opentelemetry-sdk")
34+
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
35+
+ compileOnly(project(":muzzle"))
36+
3237
compileOnly("com.google.auto.value:auto-value-annotations")
3338
annotationProcessor("com.google.auto.value:auto-value")
3439

@@ -37,7 +42,7 @@ index df605add2f..b2f01d9d4d 100644
3742

3843
// We do lightweight parsing of JSON to extract HTTP headers from requests for propagation.
3944
// This will be commonly needed even for users that don't use events, but luckily it's not too big.
40-
@@ -26,6 +26,7 @@ dependencies {
45+
@@ -26,6 +27,7 @@ dependencies {
4146

4247
testImplementation(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing"))
4348
testImplementation("uk.org.webcompere:system-stubs-jupiter")
@@ -147,10 +152,10 @@ index 9341bf6f79..f719c1ea93 100644
147152
}
148153
diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractor.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractor.java
149154
new file mode 100644
150-
index 0000000000..921a7b6b7f
155+
index 0000000000..6349d1bb29
151156
--- /dev/null
152157
+++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractor.java
153-
@@ -0,0 +1,89 @@
158+
@@ -0,0 +1,85 @@
154159
+/*
155160
+ * Copyright The OpenTelemetry Authors
156161
+ * SPDX-License-Identifier: Apache-2.0
@@ -162,9 +167,7 @@ index 0000000000..921a7b6b7f
162167
+
163168
+import io.opentelemetry.context.Context;
164169
+import io.opentelemetry.context.propagation.TextMapGetter;
165-
+import java.lang.invoke.MethodHandle;
166-
+import java.lang.invoke.MethodHandles;
167-
+import java.lang.invoke.MethodType;
170+
+import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle;
168171
+import java.util.Locale;
169172
+import java.util.Map;
170173
+import java.util.logging.Logger;
@@ -180,7 +183,7 @@ index 0000000000..921a7b6b7f
180183
+ private static final String AWS_TRACE_HEADER_PROP = "com.amazonaws.xray.traceHeader";
181184
+ // lower-case map getter used for extraction
182185
+ static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id";
183-
+ static volatile MethodHandle getXrayTraceIdHandle;
186+
+ static boolean getXrayTraceIdMethodExists = true;
184187
+
185188
+ static Context extract(
186189
+ Map<String, String> headers,
@@ -194,23 +197,21 @@ index 0000000000..921a7b6b7f
194197
+ return instrumenter.extract(mergedHeaders, MapGetter.INSTANCE);
195198
+ }
196199
+
200+
+ @NoMuzzle
197201
+ private static String getTraceHeader(
198202
+ com.amazonaws.services.lambda.runtime.Context lambdaContext) {
199203
+ String traceHeader = null;
200-
+ try {
201-
+ MethodHandle handle = getXrayTraceIdHandle;
202-
+ if (handle == null) {
203-
+ handle =
204-
+ MethodHandles.lookup()
205-
+ .findVirtual(
206-
+ lambdaContext.getClass(),
207-
+ "getXrayTraceId",
208-
+ MethodType.methodType(String.class));
209-
+ getXrayTraceIdHandle = handle;
204+
+
205+
+ // Lambda Core dependency that is actually used by Lambda Runtime may be on an older version
206+
+ // that does not have the `getXrayTraceId` method. If `NoSuchMethodError` occurs, we do not
207+
+ // attempt invoking `getXrayTraceId` again.
208+
+ if (getXrayTraceIdMethodExists) {
209+
+ try {
210+
+ traceHeader = lambdaContext.getXrayTraceId();
211+
+ } catch (NoSuchMethodError e) {
212+
+ logger.fine("Failed to get X-Ray trace ID from lambdaContext: " + e);
213+
+ getXrayTraceIdMethodExists = false;
210214
+ }
211-
+ traceHeader = (String) handle.invoke(lambdaContext);
212-
+ } catch (Throwable t) {
213-
+ logger.fine("Failed to get X-Ray trace ID via MethodHandle: " + t.getMessage());
214215
+ }
215216
+ if (traceHeader != null && !traceHeader.isEmpty()) {
216217
+ return traceHeader;
@@ -255,10 +256,10 @@ index cb19d1e568..12ed174bb2 100644
255256
assertThat(spanContext.getSpanId()).isEqualTo("00f067aa0ba902b7");
256257
diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractorTest.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractorTest.java
257258
new file mode 100644
258-
index 0000000000..e2a69ee6d8
259+
index 0000000000..4b0f354769
259260
--- /dev/null
260261
+++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractorTest.java
261-
@@ -0,0 +1,418 @@
262+
@@ -0,0 +1,375 @@
262263
+/*
263264
+ * Copyright The OpenTelemetry Authors
264265
+ * SPDX-License-Identifier: Apache-2.0
@@ -281,7 +282,6 @@ index 0000000000..e2a69ee6d8
281282
+import io.opentelemetry.context.propagation.TextMapPropagator;
282283
+import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator;
283284
+import io.opentelemetry.extension.trace.propagation.B3Propagator;
284-
+import java.lang.invoke.MethodHandle;
285285
+import java.util.Map;
286286
+import org.junit.jupiter.api.Test;
287287
+import org.junit.jupiter.api.extension.ExtendWith;
@@ -600,81 +600,39 @@ index 0000000000..e2a69ee6d8
600600
+ }
601601
+
602602
+ @Test
603-
+ void shouldFallbackToSystemPropertyWhenReflectionFails() {
603+
+ void shouldFallbackToSystemPropertyWhenNoSuchMethodErrorThrown() {
604604
+ // given
605605
+ Map<String, String> headers = ImmutableMap.of();
606-
+ // Create a mock context that doesn't have getXrayTraceId method (simulates older Lambda
607-
+ // runtime)
608-
+ Context mockLambdaContextWithoutXrayMethod = mock(Context.class);
606+
+ Context mockLambdaContextWithNoSuchMethodError = mock(Context.class);
607+
+ when(mockLambdaContextWithNoSuchMethodError.getXrayTraceId())
608+
+ .thenThrow(new NoSuchMethodError("getXrayTraceId method not found"));
609609
+ systemProperties.set(
610610
+ "com.amazonaws.xray.traceHeader",
611611
+ "Root=1-8a3c60f7-d188f8fa79d48a391a778fa7;Parent=0000000000000789;Sampled=1");
612612
+
613-
+ // when
614-
+ io.opentelemetry.context.Context context =
615-
+ ParentContextExtractor.extract(
616-
+ headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithoutXrayMethod);
617-
+ // then
618-
+ Span span = Span.fromContext(context);
619-
+ SpanContext spanContext = span.getSpanContext();
620-
+ assertThat(spanContext.isValid()).isTrue();
621-
+ assertThat(spanContext.getSpanId()).isEqualTo("0000000000000789");
622-
+ assertThat(spanContext.getTraceId()).isEqualTo("8a3c60f7d188f8fa79d48a391a778fa7");
623-
+ }
624-
+
625-
+ @Test
626-
+ void shouldFallbackToSystemPropertyWhenIllegalAccessException() {
627-
+ // given
628-
+ Map<String, String> headers = ImmutableMap.of();
629-
+ Context mockLambdaContextWithAccessException = mock(Context.class);
630-
+ when(mockLambdaContextWithAccessException.getXrayTraceId())
631-
+ .thenThrow(new RuntimeException("Simulated IllegalAccessException"));
632-
+ systemProperties.set(
633-
+ "com.amazonaws.xray.traceHeader",
634-
+ "Root=1-8a3c60f7-d188f8fa79d48a391a778fa7;Parent=0000000000000789;Sampled=1");
613+
+ // Reset the static flag to ensure the method is attempted
614+
+ ParentContextExtractor.getXrayTraceIdMethodExists = true;
635615
+
636-
+ // when
616+
+ // when - call extract
637617
+ io.opentelemetry.context.Context context =
638618
+ ParentContextExtractor.extract(
639-
+ headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithAccessException);
619+
+ headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithNoSuchMethodError);
620+
+
640621
+ // then
641622
+ Span span = Span.fromContext(context);
642623
+ SpanContext spanContext = span.getSpanContext();
643624
+ assertThat(spanContext.isValid()).isTrue();
644625
+ assertThat(spanContext.getSpanId()).isEqualTo("0000000000000789");
645626
+ assertThat(spanContext.getTraceId()).isEqualTo("8a3c60f7d188f8fa79d48a391a778fa7");
646-
+ }
647-
+
648-
+ @Test
649-
+ void shouldCacheMethodHandleAcrossMultipleInvocations() {
650-
+ // given
651-
+ Context mockLambdaContext = mock(Context.class);
652-
+ when(mockLambdaContext.getXrayTraceId())
653-
+ .thenReturn("Root=1-4fd0b613-1f19f39af59518d127b0cafe;Parent=0000000000000123;Sampled=1");
627+
+ // Verify getXrayTraceId was called only once
628+
+ assertThat(ParentContextExtractor.getXrayTraceIdMethodExists).isFalse();
629+
+ verify(mockLambdaContextWithNoSuchMethodError, times(1)).getXrayTraceId();
654630
+
655-
+ // Clear any previously cached MethodHandle
656-
+ ParentContextExtractor.getXrayTraceIdHandle = null;
657-
+
658-
+ // when - call extract multiple times (which internally calls getTraceHeader)
659-
+ assertThat(ParentContextExtractor.getXrayTraceIdHandle).isNull(); // Initially null
660-
+
661-
+ ParentContextExtractor.extract(
662-
+ ImmutableMap.of(), INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContext);
663-
+ assertThat(ParentContextExtractor.getXrayTraceIdHandle).isNotNull(); // Cached after first call
664-
+
665-
+ MethodHandle cachedHandle = ParentContextExtractor.getXrayTraceIdHandle;
666-
+
667-
+ ParentContextExtractor.extract(
668-
+ ImmutableMap.of(), INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContext);
631+
+ // when - call extract again
669632
+ ParentContextExtractor.extract(
670-
+ ImmutableMap.of(), INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContext);
671-
+
672-
+ // then - MethodHandle should remain the same (cached)
673-
+ assertThat(ParentContextExtractor.getXrayTraceIdHandle).isSameAs(cachedHandle);
674-
+
675-
+ // verify getXrayTraceId was called for each invocation (MethodHandle caching doesn't affect
676-
+ // this)
677-
+ verify(mockLambdaContext, times(3)).getXrayTraceId();
633+
+ headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithNoSuchMethodError);
634+
+ // Verify the call count of getXrayTraceId is still 1
635+
+ verify(mockLambdaContextWithNoSuchMethodError, times(1)).getXrayTraceId();
678636
+ }
679637
+}
680638
diff --git a/instrumentation/aws-lambda/aws-lambda-events-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdaevents/v2_2/AwsLambdaRequestHandlerInstrumentation.java b/instrumentation/aws-lambda/aws-lambda-events-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awslambdaevents/v2_2/AwsLambdaRequestHandlerInstrumentation.java

0 commit comments

Comments
 (0)