diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/faas/internal/FaasExceptionEventExtractors.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/faas/internal/FaasExceptionEventExtractors.java new file mode 100644 index 000000000000..0d780d5d043c --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/faas/internal/FaasExceptionEventExtractors.java @@ -0,0 +1,34 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.faas.internal; + +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.internal.Experimental; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class FaasExceptionEventExtractors { + + /** + * Configures the FaaS invocation exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + public static void setFaasInvocationExceptionEventExtractor( + InstrumenterBuilder builder) { + Experimental.setExceptionEventExtractor( + builder, + (logRecordBuilder, context, request) -> { + logRecordBuilder.setEventName("faas.invocation.exception"); + logRecordBuilder.setSeverity(Severity.ERROR); + }); + } + + private FaasExceptionEventExtractors() {} +} diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/faas/internal/FaasExceptionEventExtractorsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/faas/internal/FaasExceptionEventExtractorsTest.java new file mode 100644 index 000000000000..93f4c9ce9c73 --- /dev/null +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/faas/internal/FaasExceptionEventExtractorsTest.java @@ -0,0 +1,57 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.faas.internal; + +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; + +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; +import java.util.List; +import org.assertj.core.api.AbstractAssert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class FaasExceptionEventExtractorsTest { + + @RegisterExtension + static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); + + @Test + void faasInvocationExceptionLog() { + InstrumenterBuilder builder = + Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", unused -> "span"); + FaasExceptionEventExtractors.setFaasInvocationExceptionEventExtractor(builder); + Instrumenter instrumenter = builder.buildInstrumenter(); + + Context context = instrumenter.start(Context.root(), "request"); + IllegalStateException error = new IllegalStateException("test"); + instrumenter.end(context, "request", "response", error); + + List logs = otelTesting.getLogRecords(); + if (emitExceptionAsLogs()) { + assertThat(logs).hasSize(1); + assertThat(logs.get(0)) + .hasSeverity(Severity.ERROR) + .hasEventName("faas.invocation.exception") + .hasAttributesSatisfyingExactly( + equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"), + equalTo(EXCEPTION_MESSAGE, "test"), + satisfies(EXCEPTION_STACKTRACE, AbstractAssert::isNotNull)); + } else { + assertThat(logs).isEmpty(); + } + } +} diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/build.gradle.kts b/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/build.gradle.kts index 0c71782903d3..f4625ed2c3c4 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/build.gradle.kts +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/build.gradle.kts @@ -20,11 +20,25 @@ dependencies { testImplementation(project(":instrumentation:aws-lambda:aws-lambda-core-1.0:testing")) } -tasks.test { - // required on jdk17 - jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") - jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") - jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") +tasks { + withType().configureEach { + // required on jdk17 + jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED") + jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") + jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") - systemProperty("collectMetadata", otelProps.collectMetadata) + systemProperty("collectMetadata", otelProps.collectMetadata) + } + + val testExceptionSignalLogs by registering(Test::class) { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + jvmArgs("-Dotel.semconv.exception.signal.preview=logs") + systemProperty("metadataConfig", "otel.semconv.exception.signal.preview=logs") + } + + check { + dependsOn(testExceptionSignalLogs) + } } diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awslambdacore/v1_0/AwsLambdaStreamHandlerTest.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awslambdacore/v1_0/AwsLambdaStreamHandlerTest.java index 30538b1ff5ab..acb2c8cc7470 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awslambdacore/v1_0/AwsLambdaStreamHandlerTest.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awslambdacore/v1_0/AwsLambdaStreamHandlerTest.java @@ -5,15 +5,18 @@ package io.opentelemetry.javaagent.instrumentation.awslambdacore.v1_0; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INVOCATION_ID; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import static org.mockito.Mockito.when; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; @@ -86,8 +89,18 @@ void handlerTracedWithException() { span.hasName("my_function") .hasKind(SpanKind.SERVER) .hasStatus(StatusData.error()) - .hasException(thrown) + .hasException(emitExceptionAsSpanEvents() ? thrown : null) .hasAttributesSatisfyingExactly(equalTo(FAAS_INVOCATION_ID, "1-22-333")))); + + if (emitExceptionAsLogs()) { + testing.waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.ERROR) + .hasEventName("faas.invocation.exception") + .hasException(thrown) + .hasTotalAttributeCount(3)); + } } private static class RequestStreamHandlerTestImpl implements RequestStreamHandler { 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 index df605add2f71..d4848deb307a 100644 --- 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 @@ -34,3 +34,16 @@ tasks.withType().configureEach { jvmArgs("--add-opens=java.base/java.util=ALL-UNNAMED") jvmArgs("-XX:+IgnoreUnrecognizedVMOptions") } + +tasks { + val testExceptionSignalLogs by registering(Test::class) { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + jvmArgs("-Dotel.semconv.exception.signal.preview=logs") + } + + check { + dependsOn(testExceptionSignalLogs) + } +} diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenterFactory.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenterFactory.java index 277c358ca8e2..4f97ac1600af 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenterFactory.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/internal/AwsLambdaFunctionInstrumenterFactory.java @@ -5,8 +5,11 @@ package io.opentelemetry.instrumentation.awslambdacore.v1_0.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.faas.internal.FaasExceptionEventExtractors.setFaasInvocationExceptionEventExtractor; + import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest; @@ -17,14 +20,16 @@ public final class AwsLambdaFunctionInstrumenterFactory { public static AwsLambdaFunctionInstrumenter createInstrumenter(OpenTelemetry openTelemetry) { - return new AwsLambdaFunctionInstrumenter( - openTelemetry, - Instrumenter.builder( + InstrumenterBuilder builder = + Instrumenter.builder( openTelemetry, "io.opentelemetry.aws-lambda-core-1.0", AwsLambdaFunctionInstrumenterFactory::spanName) - .addAttributesExtractor(new AwsLambdaFunctionAttributesExtractor()) - .buildInstrumenter(SpanKindExtractor.alwaysServer())); + .addAttributesExtractor(new AwsLambdaFunctionAttributesExtractor()); + setFaasInvocationExceptionEventExtractor(builder); + + return new AwsLambdaFunctionInstrumenter( + openTelemetry, builder.buildInstrumenter(SpanKindExtractor.alwaysServer())); } private static String spanName(AwsLambdaRequest input) { diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperHttpPropagationTest.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperHttpPropagationTest.java index 5394d7dd5e01..fc4e5e1bdb0d 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperHttpPropagationTest.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperHttpPropagationTest.java @@ -5,12 +5,14 @@ package io.opentelemetry.instrumentation.awslambdacore.v1_0; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_ACCOUNT_ID; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_RESOURCE_ID; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INVOCATION_ID; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import static org.mockito.Mockito.when; @@ -19,6 +21,7 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; +import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.WrappedLambda; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; @@ -126,13 +129,23 @@ void handlerTracedWithException() { .hasTraceId("4fd0b6131f19f39af59518d127b0cafe") .hasParentSpanId("0000000000000456") .hasStatus(StatusData.error()) - .hasException(thrown) + .hasException(emitExceptionAsSpanEvents() ? thrown : null) .hasAttributesSatisfyingExactly( equalTo( CLOUD_RESOURCE_ID, "arn:aws:lambda:us-east-1:123456789:function:test"), equalTo(CLOUD_ACCOUNT_ID, "123456789"), equalTo(FAAS_INVOCATION_ID, "1-22-333")))); + + if (emitExceptionAsLogs()) { + testing.waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.ERROR) + .hasEventName("faas.invocation.exception") + .hasException(thrown) + .hasTotalAttributeCount(3)); + } } public static class TestRequestHandler implements RequestStreamHandler { diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperTest.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperTest.java index 08b024f38441..a3c80e1d2237 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperTest.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/library/src/test/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AwsLambdaStreamWrapperTest.java @@ -5,17 +5,20 @@ package io.opentelemetry.instrumentation.awslambdacore.v1_0; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_ACCOUNT_ID; import static io.opentelemetry.semconv.incubating.CloudIncubatingAttributes.CLOUD_RESOURCE_ID; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INVOCATION_ID; import static java.nio.charset.StandardCharsets.UTF_8; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import static org.mockito.Mockito.when; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; +import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.WrappedLambda; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; @@ -107,13 +110,23 @@ void handlerTracedWithException() { span.hasName("my_function") .hasKind(SpanKind.SERVER) .hasStatus(StatusData.error()) - .hasException(thrown) + .hasException(emitExceptionAsSpanEvents() ? thrown : null) .hasAttributesSatisfyingExactly( equalTo( CLOUD_RESOURCE_ID, "arn:aws:lambda:us-east-1:123456789:function:test"), equalTo(CLOUD_ACCOUNT_ID, "123456789"), equalTo(FAAS_INVOCATION_ID, "1-22-333")))); + + if (emitExceptionAsLogs()) { + testing.waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.ERROR) + .hasEventName("faas.invocation.exception") + .hasException(thrown) + .hasTotalAttributeCount(3)); + } } public static class TestRequestHandler implements RequestStreamHandler { diff --git a/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AbstractAwsLambdaTest.java b/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AbstractAwsLambdaTest.java index 209a0bd31a95..a5a2fd2040c7 100644 --- a/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AbstractAwsLambdaTest.java +++ b/instrumentation/aws-lambda/aws-lambda-core-1.0/testing/src/main/java/io/opentelemetry/instrumentation/awslambdacore/v1_0/AbstractAwsLambdaTest.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.awslambdacore.v1_0; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.semconv.incubating.FaasIncubatingAttributes.FAAS_INVOCATION_ID; @@ -13,6 +15,7 @@ import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; +import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; import io.opentelemetry.sdk.trace.data.StatusData; @@ -84,9 +87,20 @@ void handlerTracedWithException() { span.hasName("my_function") .hasKind(SpanKind.SERVER) .hasStatus(StatusData.error()) - .hasException(thrown) + .hasException(emitExceptionAsSpanEvents() ? thrown : null) .hasAttributesSatisfyingExactly( equalTo(FAAS_INVOCATION_ID, "1-22-333")))); + + if (emitExceptionAsLogs()) { + testing() + .waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.ERROR) + .hasEventName("faas.invocation.exception") + .hasException(thrown) + .hasTotalAttributeCount(3)); + } } /** diff --git a/instrumentation/aws-lambda/aws-lambda-events-common-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/common/v2_2/internal/AwsLambdaEventsInstrumenterFactory.java b/instrumentation/aws-lambda/aws-lambda-events-common-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/common/v2_2/internal/AwsLambdaEventsInstrumenterFactory.java index e5d615113253..cf3d676e9e6c 100644 --- a/instrumentation/aws-lambda/aws-lambda-events-common-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/common/v2_2/internal/AwsLambdaEventsInstrumenterFactory.java +++ b/instrumentation/aws-lambda/aws-lambda-events-common-2.2/library/src/main/java/io/opentelemetry/instrumentation/awslambdaevents/common/v2_2/internal/AwsLambdaEventsInstrumenterFactory.java @@ -5,9 +5,12 @@ package io.opentelemetry.instrumentation.awslambdaevents.common.v2_2.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.faas.internal.FaasExceptionEventExtractors.setFaasInvocationExceptionEventExtractor; + import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.awslambdacore.v1_0.AwsLambdaRequest; import io.opentelemetry.instrumentation.awslambdacore.v1_0.internal.AwsLambdaFunctionAttributesExtractor; @@ -22,13 +25,15 @@ public final class AwsLambdaEventsInstrumenterFactory { public static AwsLambdaFunctionInstrumenter createInstrumenter( OpenTelemetry openTelemetry, String instrumentationName, Set knownMethods) { - return new AwsLambdaFunctionInstrumenter( - openTelemetry, - Instrumenter.builder( + InstrumenterBuilder builder = + Instrumenter.builder( openTelemetry, instrumentationName, AwsLambdaEventsInstrumenterFactory::spanName) .addAttributesExtractor(new AwsLambdaFunctionAttributesExtractor()) - .addAttributesExtractor(new ApiGatewayProxyAttributesExtractor(knownMethods)) - .buildInstrumenter(SpanKindExtractor.alwaysServer())); + .addAttributesExtractor(new ApiGatewayProxyAttributesExtractor(knownMethods)); + setFaasInvocationExceptionEventExtractor(builder); + + return new AwsLambdaFunctionInstrumenter( + openTelemetry, builder.buildInstrumenter(SpanKindExtractor.alwaysServer())); } private static String spanName(AwsLambdaRequest input) {