Skip to content

Commit 0935bd0

Browse files
committed
cache method for getXrayTraceId, and use MethodHandle instead
1 parent beea0d0 commit 0935bd0

File tree

1 file changed

+81
-9
lines changed

1 file changed

+81
-9
lines changed

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

Lines changed: 81 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ index 9341bf6f79..f719c1ea93 100644
147147
}
148148
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
149149
new file mode 100644
150-
index 0000000000..9bea9808a5
150+
index 0000000000..921a7b6b7f
151151
--- /dev/null
152152
+++ 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,76 @@
153+
@@ -0,0 +1,89 @@
154154
+/*
155155
+ * Copyright The OpenTelemetry Authors
156156
+ * SPDX-License-Identifier: Apache-2.0
@@ -162,6 +162,9 @@ index 0000000000..9bea9808a5
162162
+
163163
+import io.opentelemetry.context.Context;
164164
+import io.opentelemetry.context.propagation.TextMapGetter;
165+
+import java.lang.invoke.MethodHandle;
166+
+import java.lang.invoke.MethodHandles;
167+
+import java.lang.invoke.MethodType;
165168
+import java.util.Locale;
166169
+import java.util.Map;
167170
+import java.util.logging.Logger;
@@ -177,6 +180,7 @@ index 0000000000..9bea9808a5
177180
+ private static final String AWS_TRACE_HEADER_PROP = "com.amazonaws.xray.traceHeader";
178181
+ // lower-case map getter used for extraction
179182
+ static final String AWS_TRACE_HEADER_PROPAGATOR_KEY = "x-amzn-trace-id";
183+
+ static volatile MethodHandle getXrayTraceIdHandle;
180184
+
181185
+ static Context extract(
182186
+ Map<String, String> headers,
@@ -194,10 +198,19 @@ index 0000000000..9bea9808a5
194198
+ com.amazonaws.services.lambda.runtime.Context lambdaContext) {
195199
+ String traceHeader = null;
196200
+ try {
197-
+ // Use reflection to avoid muzzle issues with getXrayTraceId method
198-
+ traceHeader = (String) lambdaContext.getClass().getMethod("getXrayTraceId").invoke(lambdaContext);
199-
+ } catch (Exception e) {
200-
+ logger.fine("Failed to get X-Ray trace ID via reflection: " + e.getMessage());
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;
210+
+ }
211+
+ traceHeader = (String) handle.invoke(lambdaContext);
212+
+ } catch (Throwable t) {
213+
+ logger.fine("Failed to get X-Ray trace ID via MethodHandle: " + t.getMessage());
201214
+ }
202215
+ if (traceHeader != null && !traceHeader.isEmpty()) {
203216
+ return traceHeader;
@@ -242,10 +255,10 @@ index cb19d1e568..12ed174bb2 100644
242255
assertThat(spanContext.getSpanId()).isEqualTo("00f067aa0ba902b7");
243256
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
244257
new file mode 100644
245-
index 0000000000..edca3ce68c
258+
index 0000000000..e2a69ee6d8
246259
--- /dev/null
247260
+++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/ParentContextExtractorTest.java
248-
@@ -0,0 +1,359 @@
261+
@@ -0,0 +1,418 @@
249262
+/*
250263
+ * Copyright The OpenTelemetry Authors
251264
+ * SPDX-License-Identifier: Apache-2.0
@@ -255,6 +268,8 @@ index 0000000000..edca3ce68c
255268
+
256269
+import static org.assertj.core.api.Assertions.assertThat;
257270
+import static org.mockito.Mockito.mock;
271+
+import static org.mockito.Mockito.times;
272+
+import static org.mockito.Mockito.verify;
258273
+import static org.mockito.Mockito.when;
259274
+
260275
+import com.amazonaws.services.lambda.runtime.Context;
@@ -266,6 +281,7 @@ index 0000000000..edca3ce68c
266281
+import io.opentelemetry.context.propagation.TextMapPropagator;
267282
+import io.opentelemetry.contrib.awsxray.propagator.AwsXrayPropagator;
268283
+import io.opentelemetry.extension.trace.propagation.B3Propagator;
284+
+import java.lang.invoke.MethodHandle;
269285
+import java.util.Map;
270286
+import org.junit.jupiter.api.Test;
271287
+import org.junit.jupiter.api.extension.ExtendWith;
@@ -587,7 +603,8 @@ index 0000000000..edca3ce68c
587603
+ void shouldFallbackToSystemPropertyWhenReflectionFails() {
588604
+ // given
589605
+ Map<String, String> headers = ImmutableMap.of();
590-
+ // Create a mock context that doesn't have getXrayTraceId method (simulates older Lambda runtime)
606+
+ // Create a mock context that doesn't have getXrayTraceId method (simulates older Lambda
607+
+ // runtime)
591608
+ Context mockLambdaContextWithoutXrayMethod = mock(Context.class);
592609
+ systemProperties.set(
593610
+ "com.amazonaws.xray.traceHeader",
@@ -604,6 +621,61 @@ index 0000000000..edca3ce68c
604621
+ assertThat(spanContext.getSpanId()).isEqualTo("0000000000000789");
605622
+ assertThat(spanContext.getTraceId()).isEqualTo("8a3c60f7d188f8fa79d48a391a778fa7");
606623
+ }
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");
635+
+
636+
+ // when
637+
+ io.opentelemetry.context.Context context =
638+
+ ParentContextExtractor.extract(
639+
+ headers, INSTRUMENTER_WITH_B3_XRAY_PROPAGATORS, mockLambdaContextWithAccessException);
640+
+ // then
641+
+ Span span = Span.fromContext(context);
642+
+ SpanContext spanContext = span.getSpanContext();
643+
+ assertThat(spanContext.isValid()).isTrue();
644+
+ assertThat(spanContext.getSpanId()).isEqualTo("0000000000000789");
645+
+ 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");
654+
+
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);
669+
+ 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();
678+
+ }
607679
+}
608680
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
609681
index e059250807..1fa80c3735 100644

0 commit comments

Comments
 (0)