@@ -25,10 +25,15 @@ index a6b89d253d..e62d30eddb 100644
2525 if (!functionInstrumenter().shouldStart(parentContext, otelInput)) {
2626 return;
2727diff --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 }
148153diff --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
149154new file mode 100644
150- index 0000000000..e711558e05
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,68 @@
158+ @@ -0,0 +1,85 @@
154159+ /*
155160+ * Copyright The OpenTelemetry Authors
156161+ * SPDX-License-Identifier: Apache-2.0
@@ -162,19 +167,23 @@ index 0000000000..e711558e05
162167+
163168+ import io.opentelemetry.context.Context;
164169+ import io.opentelemetry.context.propagation.TextMapGetter;
170+ + import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle;
165171+ import java.util.Locale;
166172+ import java.util.Map;
173+ + import java.util.logging.Logger;
167174+
168175+ /**
169176+ * This class is internal and is hence not for public use. Its APIs are unstable and can change at
170177+ * any time.
171178+ */
172179+ public final class ParentContextExtractor {
173180+
181+ + private static final Logger logger = Logger.getLogger(ParentContextExtractor.class.getName());
174182+ private static final String AWS_TRACE_HEADER_ENV_KEY = "_X_AMZN_TRACE_ID";
175183+ private static final String AWS_TRACE_HEADER_PROP = "com.amazonaws.xray.traceHeader";
176184+ // lower-case map getter used for extraction
177185+ static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id";
186+ + static boolean getXrayTraceIdMethodExists = true;
178187+
179188+ static Context extract(
180189+ Map<String, String> headers,
@@ -188,9 +197,22 @@ index 0000000000..e711558e05
188197+ return instrumenter.extract(mergedHeaders, MapGetter.INSTANCE);
189198+ }
190199+
200+ + @NoMuzzle
191201+ private static String getTraceHeader(
192202+ com.amazonaws.services.lambda.runtime.Context lambdaContext) {
193- + String traceHeader = lambdaContext.getXrayTraceId();
203+ + String traceHeader = null;
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;
214+ + }
215+ + }
194216+ if (traceHeader != null && !traceHeader.isEmpty()) {
195217+ return traceHeader;
196218+ }
@@ -234,10 +256,10 @@ index cb19d1e568..12ed174bb2 100644
234256 assertThat(spanContext.getSpanId()).isEqualTo("00f067aa0ba902b7");
235257diff --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
236258new file mode 100644
237- index 0000000000..76fc823a65
259+ index 0000000000..4b0f354769
238260--- /dev/null
239261+++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractorTest.java
240- @@ -0,0 +1,337 @@
262+ @@ -0,0 +1,375 @@
241263+ /*
242264+ * Copyright The OpenTelemetry Authors
243265+ * SPDX-License-Identifier: Apache-2.0
@@ -247,6 +269,8 @@ index 0000000000..76fc823a65
247269+
248270+ import static org.assertj.core.api.Assertions.assertThat;
249271+ import static org.mockito.Mockito.mock;
272+ + import static org.mockito.Mockito.times;
273+ + import static org.mockito.Mockito.verify;
250274+ import static org.mockito.Mockito.when;
251275+
252276+ import com.amazonaws.services.lambda.runtime.Context;
@@ -574,6 +598,42 @@ index 0000000000..76fc823a65
574598+ assertThat(spanContext.getSpanId()).isEqualTo("0000000000000789");
575599+ assertThat(spanContext.getTraceId()).isEqualTo("8a3c60f7d188f8fa79d48a391a778fa7");
576600+ }
601+ +
602+ + @Test
603+ + void shouldFallbackToSystemPropertyWhenNoSuchMethodErrorThrown() {
604+ + // given
605+ + Map<String, String> headers = ImmutableMap.of();
606+ + Context mockLambdaContextWithNoSuchMethodError = mock(Context.class);
607+ + when(mockLambdaContextWithNoSuchMethodError.getXrayTraceId())
608+ + .thenThrow(new NoSuchMethodError("getXrayTraceId method not found"));
609+ + systemProperties.set(
610+ + "com.amazonaws.xray.traceHeader",
611+ + "Root=1-8a3c60f7-d188f8fa79d48a391a778fa7;Parent=0000000000000789;Sampled=1");
612+ +
613+ + // Reset the static flag to ensure the method is attempted
614+ + ParentContextExtractor.getXrayTraceIdMethodExists = true;
615+ +
616+ + // when - call extract
617+ + io.opentelemetry.context.Context context =
618+ + ParentContextExtractor.extract(
619+ + headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithNoSuchMethodError);
620+ +
621+ + // then
622+ + Span span = Span.fromContext(context);
623+ + SpanContext spanContext = span.getSpanContext();
624+ + assertThat(spanContext.isValid()).isTrue();
625+ + assertThat(spanContext.getSpanId()).isEqualTo("0000000000000789");
626+ + assertThat(spanContext.getTraceId()).isEqualTo("8a3c60f7d188f8fa79d48a391a778fa7");
627+ + // Verify getXrayTraceId was called only once
628+ + assertThat(ParentContextExtractor.getXrayTraceIdMethodExists).isFalse();
629+ + verify(mockLambdaContextWithNoSuchMethodError, times(1)).getXrayTraceId();
630+ +
631+ + // when - call extract again
632+ + ParentContextExtractor.extract(
633+ + headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithNoSuchMethodError);
634+ + // Verify the call count of getXrayTraceId is still 1
635+ + verify(mockLambdaContextWithNoSuchMethodError, times(1)).getXrayTraceId();
636+ + }
577637+ }
578638diff --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
579639index e059250807..1fa80c3735 100644
@@ -614,7 +674,7 @@ index 4cd11fc0c4..7b7d62755c 100644
614674 }
615675
616676diff --git a/version.gradle.kts b/version.gradle.kts
617- index 7900c9a4d9..80383d7c22 100644
677+ index ec9690086c..b267166804 100644
618678--- a/version.gradle.kts
619679+++ b/version.gradle.kts
620680@@ -1,5 +1,5 @@
0 commit comments