From 86d7487ff962cf9194fd63a8749444049d046f21 Mon Sep 17 00:00:00 2001 From: Ayushi Ahjolia Date: Mon, 17 Aug 2026 14:07:41 -0700 Subject: [PATCH 1/2] feat(otel): Add per-PR OTel conformance test suite --- .github/workflows/otel-conformance-tests.yml | 115 ++++ conformance-tests-otel/pom.xml | 121 ++++ .../otel/Otel10WaitForCallback.java | 16 + .../conformance/otel/Otel11ChainedInvoke.java | 21 + .../conformance/otel/Otel11InvokeTarget.java | 15 + .../otel/Otel12ChildContextFailure.java | 18 + .../otel/Otel13ParallelFailure.java | 27 + .../conformance/otel/Otel14MapFailure.java | 29 + .../otel/Otel15WaitInterrupted.java | 17 + .../otel/Otel16WaitForConditionFailure.java | 18 + .../otel/Otel17WaitForCallbackFailure.java | 16 + .../otel/Otel18ChainedInvokeFailure.java | 17 + .../conformance/otel/Otel18InvokeTarget.java | 15 + .../otel/Otel19ExecutionFailure.java | 16 + .../conformance/otel/Otel1Success.java | 16 + .../conformance/otel/Otel2WaitResume.java | 18 + .../durable/conformance/otel/Otel3Retry.java | 30 + .../otel/Otel4TerminalFailure.java | 26 + .../conformance/otel/Otel5ChildContext.java | 19 + .../conformance/otel/Otel6Parallel.java | 33 + .../durable/conformance/otel/Otel7Map.java | 25 + .../conformance/otel/Otel8HandledFailure.java | 31 + .../otel/Otel9WaitForCondition.java | 32 + .../otel/OtelConformanceHandler.java | 60 ++ .../otel/OtelLongRunning1Wait.java | 18 + .../otel/OtelLongRunning2Retry.java | 30 + .../otel/OtelLongRunning3Callback.java | 17 + .../otel/OtelLongRunning4ChainedInvoke.java | 21 + .../otel/OtelLongRunning4InvokeTarget.java | 18 + .../template-long-running.yaml | 110 ++++ conformance-tests-otel/template.yaml | 578 ++++++++++++++++++ 31 files changed, 1543 insertions(+) create mode 100644 .github/workflows/otel-conformance-tests.yml create mode 100644 conformance-tests-otel/pom.xml create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel10WaitForCallback.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11ChainedInvoke.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11InvokeTarget.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel12ChildContextFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel13ParallelFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel14MapFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel15WaitInterrupted.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel16WaitForConditionFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel17WaitForCallbackFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18ChainedInvokeFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18InvokeTarget.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel19ExecutionFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel1Success.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel2WaitResume.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel3Retry.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel4TerminalFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel5ChildContext.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel6Parallel.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel7Map.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel8HandledFailure.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel9WaitForCondition.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelConformanceHandler.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning1Wait.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning2Retry.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning3Callback.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4ChainedInvoke.java create mode 100644 conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4InvokeTarget.java create mode 100644 conformance-tests-otel/template-long-running.yaml create mode 100644 conformance-tests-otel/template.yaml diff --git a/.github/workflows/otel-conformance-tests.yml b/.github/workflows/otel-conformance-tests.yml new file mode 100644 index 000000000..d32843582 --- /dev/null +++ b/.github/workflows/otel-conformance-tests.yml @@ -0,0 +1,115 @@ +name: OTel Conformance Tests + +# Per-PR OpenTelemetry conformance run. Reuses the shared orchestrator from +# aws-durable-execution-conformance-tests and points it at this repo's own handlers/templates +# (conformance-tests-otel/) via examples_dir, so the handlers live here while the orchestration +# (backend matrix, ADOT layer, collector build, long-running cycle) stays centralized. +# +# Mirrors the Java preset's language config (setup/prepare commands, ADOT repo, runtime) but calls +# opentelemetry-orchestrator.yml directly, matching the Python SDK's caller. + +on: + pull_request: + branches: [main] + paths: + - "sdk/**" + - "otel-plugin/**" + - "conformance-tests-otel/**" + - "pom.xml" + - ".github/workflows/otel-conformance-tests.yml" + push: + branches: [main] + paths: + - "sdk/**" + - "otel-plugin/**" + - "conformance-tests-otel/**" + - "pom.xml" + - ".github/workflows/otel-conformance-tests.yml" + workflow_dispatch: + inputs: + phase: + description: Run short tests, launch a long run, or check the active long run + required: true + default: short + type: choice + options: + - short + - launch + - check + delay_seconds: + description: Durable delay in seconds (1-86400, launch only) + required: true + default: "82800" + type: string + aws_region: + description: AWS region + required: true + default: us-west-2 + type: string + conformance_test_ref: + description: Optional conformance test commit SHA or branch name + required: false + type: string + +permissions: {} + +jobs: + opentelemetry: + permissions: + actions: write + contents: read + id-token: write + uses: aws/aws-durable-execution-conformance-tests/.github/workflows/opentelemetry-orchestrator.yml@0f0b5bda84116ef77034451b9c4c21774e76d8e4 + with: + language: java + resource_prefix: j + sdk_repository: aws/aws-durable-execution-sdk-java + sdk_ref: ${{ github.event.pull_request.head.sha || github.sha }} + conformance_test_ref: ${{ inputs.conformance_test_ref || 'main' }} + checkout_sdk: true + # Build the handlers from this repo's checked-out module instead of the conformance repo's + # bundled examples/java. Path is relative to the conformance workspace where the SDK is + # checked out (.build/durable-sdk). + examples_dir: .build/durable-sdk/conformance-tests-otel + setup_command: | + if [ -z "${JAVA_HOME_21_X64:-}" ]; then + echo "The runner does not provide Java 21" + exit 1 + fi + export JAVA_HOME="$JAVA_HOME_21_X64" + export PATH="$JAVA_HOME/bin:$PATH" + java -version + prepare_command: | + JAVA_SDK_VERSION=$( + mvn -B -q \ + --file "$SDK_CHECKOUT/pom.xml" \ + -Dstyle.color=never \ + -Dexpression=project.version \ + -DforceStdout \ + help:evaluate + ) + mvn -B -q \ + --file "$SDK_CHECKOUT/pom.xml" \ + --projects sdk,otel-plugin \ + --also-make \ + -DskipTests \ + install + echo "Using Java SDK version $JAVA_SDK_VERSION" + echo "JAVA_SDK_VERSION=$JAVA_SDK_VERSION" >> "$GITHUB_ENV" + mvn -B -q -DskipTests package \ + -Ddurable.sdk.version="$JAVA_SDK_VERSION" \ + --file "$EXAMPLES_DIR/pom.xml" + adot_release_repository: aws-observability/aws-otel-java-instrumentation + collector_compatible_runtime: java21 + collector_otlp_endpoint: http://localhost:4318 + phase: ${{ inputs.phase || 'short' }} + delay_seconds: ${{ inputs.delay_seconds || '82800' }} + aws_region: ${{ inputs.aws_region || 'us-west-2' }} + secrets: + CONFORMANCE_TEST_ROLE_ARN: ${{ secrets.TEST_ROLE_ARN }} + CONFORMANCE_TEST_ACCOUNT_ID: ${{ secrets.TEST_ACCOUNT_ID }} + CONFORMANCE_TEST_LAMBDA_EXECUTION_ROLE_ARN: ${{ secrets.TEST_LAMBDA_EXECUTION_ROLE_ARN }} + DASH0_AUTH_TOKEN: ${{ secrets.DASH0_AUTH_TOKEN }} + DATADOG_ACCESS_TOKEN: ${{ secrets.DATADOG_ACCESS_TOKEN }} + DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }} + DATADOG_APPLICATION_KEY: ${{ secrets.DATADOG_APPLICATION_KEY }} diff --git a/conformance-tests-otel/pom.xml b/conformance-tests-otel/pom.xml new file mode 100644 index 000000000..2d1f0106b --- /dev/null +++ b/conformance-tests-otel/pom.xml @@ -0,0 +1,121 @@ + + + 4.0.0 + + + software.amazon.lambda.durable + aws-durable-execution-sdk-java-conformance-tests-otel + 1.0.0 + jar + + AWS Lambda Durable Execution SDK OpenTelemetry Conformance Tests + + Java SDK handlers and SAM templates for the durable execution OpenTelemetry conformance + suite (otel-invocation, otel-execution, and otel-long-running). Built and deployed by the + shared OpenTelemetry conformance workflow. + + + + UTF-8 + 17 + 17 + 17 + + ${env.JAVA_SDK_VERSION} + 1.65.0 + 1.4.0 + + + + + software.amazon.lambda.durable + aws-durable-execution-sdk-java + ${durable.sdk.version} + + + software.amazon.lambda.durable + aws-durable-execution-sdk-java-plugin-otel + ${durable.sdk.version} + + + io.opentelemetry + opentelemetry-sdk + ${opentelemetry.version} + + + com.amazonaws + aws-lambda-java-core + ${aws.lambda.java.core.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.15.0 + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.11.0 + + + copy-otel-javaagent-extension + prepare-package + + copy + + + + + software.amazon.lambda.durable + aws-durable-execution-sdk-java-plugin-otel + ${durable.sdk.version} + ${project.build.outputDirectory}/lib + otel-plugin-extension.jar + + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.2 + + false + + + + package + + shade + + + + + + + + + + + + diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel10WaitForCallback.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel10WaitForCallback.java new file mode 100644 index 000000000..257c8f28e --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel10WaitForCallback.java @@ -0,0 +1,16 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Wait-for-callback scenario for OTel requirement otel-invocation-10. */ +public final class Otel10WaitForCallback extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "wait-for-callback"); + return context.waitForCallback("otel-callback", String.class, (callbackId, step) -> {}); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11ChainedInvoke.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11ChainedInvoke.java new file mode 100644 index 000000000..b2d50e822 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11ChainedInvoke.java @@ -0,0 +1,21 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.TypeToken; + +/** Chained-invoke scenario for OTel requirement otel-invocation-11. */ +public final class Otel11ChainedInvoke extends OtelConformanceHandler> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + requireScenario(event, "chained-invoke"); + return context.invoke( + "otel-invoke", + System.getenv("OTEL_INVOKE_TARGET_FUNCTION_NAME"), + event, + new TypeToken>() {}); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11InvokeTarget.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11InvokeTarget.java new file mode 100644 index 000000000..a81960320 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel11InvokeTarget.java @@ -0,0 +1,15 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Successful chained-invoke target for OTel requirement otel-invocation-11. */ +public final class Otel11InvokeTarget extends OtelConformanceHandler> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + return event; + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel12ChildContextFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel12ChildContextFailure.java new file mode 100644 index 000000000..cd114d44a --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel12ChildContextFailure.java @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Failed child-context scenario for OTel requirement otel-invocation-12. */ +public final class Otel12ChildContextFailure extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "child-context-failure"); + return context.runInChildContext("otel-failed-child-context", Void.class, child -> { + throw new RuntimeException("Intentional child-context failure"); + }); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel13ParallelFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel13ParallelFailure.java new file mode 100644 index 000000000..0dcb43531 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel13ParallelFailure.java @@ -0,0 +1,27 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableFuture; +import software.amazon.lambda.durable.config.ParallelConfig; + +/** Failed parallel-branch scenario for OTel requirement otel-invocation-13. */ +public final class Otel13ParallelFailure extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "parallel-failure"); + var parallel = context.parallel( + "otel-failed-parallel", + ParallelConfig.builder().maxConcurrency(1).build()); + DurableFuture failedBranch; + try (parallel) { + failedBranch = parallel.branch("otel-failed-parallel-branch", Void.class, branch -> { + throw new RuntimeException("Intentional parallel branch failure"); + }); + } + return failedBranch.get(); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel14MapFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel14MapFailure.java new file mode 100644 index 000000000..daf428f8f --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel14MapFailure.java @@ -0,0 +1,29 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.List; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.MapConfig; + +/** Failed map-iteration scenario for OTel requirement otel-invocation-14. */ +public final class Otel14MapFailure extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "map-failure"); + var result = context.map( + "otel-failed-map", + List.of(1), + Void.class, + (item, index, iteration) -> { + throw new RuntimeException("Intentional map iteration failure"); + }, + MapConfig.builder().maxConcurrency(1).build()); + if (!result.allSucceeded()) { + throw new RuntimeException("Intentional map failure"); + } + return null; + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel15WaitInterrupted.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel15WaitInterrupted.java new file mode 100644 index 000000000..d406168d7 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel15WaitInterrupted.java @@ -0,0 +1,17 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Interrupted wait scenario for OTel requirement otel-invocation-15. */ +public final class Otel15WaitInterrupted extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "wait-interrupted"); + return context.wait("otel-interrupted-wait", Duration.ofSeconds(30)); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel16WaitForConditionFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel16WaitForConditionFailure.java new file mode 100644 index 000000000..91c8864f1 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel16WaitForConditionFailure.java @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Failed wait-for-condition scenario for OTel requirement otel-invocation-16. */ +public final class Otel16WaitForConditionFailure extends OtelConformanceHandler { + + @Override + public Integer handleRequest(Map event, DurableContext context) { + requireScenario(event, "wait-for-condition-failure"); + return context.waitForCondition("otel-failed-condition", Integer.class, (state, step) -> { + throw new RuntimeException("Intentional condition check failure"); + }); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel17WaitForCallbackFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel17WaitForCallbackFailure.java new file mode 100644 index 000000000..3549d5e0e --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel17WaitForCallbackFailure.java @@ -0,0 +1,16 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Failed wait-for-callback scenario for OTel requirement otel-invocation-17. */ +public final class Otel17WaitForCallbackFailure extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "wait-for-callback-failure"); + return context.waitForCallback("otel-failed-callback", String.class, (callbackId, step) -> {}); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18ChainedInvokeFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18ChainedInvokeFailure.java new file mode 100644 index 000000000..6810db129 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18ChainedInvokeFailure.java @@ -0,0 +1,17 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Failed chained-invoke scenario for OTel requirement otel-invocation-18. */ +public final class Otel18ChainedInvokeFailure extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "chained-invoke-failure"); + return context.invoke( + "otel-failed-invoke", System.getenv("OTEL_INVOKE_TARGET_FUNCTION_NAME"), event, Void.class); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18InvokeTarget.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18InvokeTarget.java new file mode 100644 index 000000000..807fc89b4 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel18InvokeTarget.java @@ -0,0 +1,15 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Failed chained-invoke target for OTel requirement otel-invocation-18. */ +public final class Otel18InvokeTarget extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + throw new RuntimeException("Intentional chained-invoke target failure"); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel19ExecutionFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel19ExecutionFailure.java new file mode 100644 index 000000000..b22cbc1eb --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel19ExecutionFailure.java @@ -0,0 +1,16 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Direct handler failure scenario for OTel requirement otel-invocation-19. */ +public final class Otel19ExecutionFailure extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "execution-failure"); + throw new RuntimeException("Intentional execution failure"); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel1Success.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel1Success.java new file mode 100644 index 000000000..edda4714f --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel1Success.java @@ -0,0 +1,16 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Successful step scenario for OTel requirement otel-invocation-1. */ +public final class Otel1Success extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "success"); + return context.step("otel-success", String.class, step -> "success"); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel2WaitResume.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel2WaitResume.java new file mode 100644 index 000000000..35bd7aa7d --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel2WaitResume.java @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Wait-and-resume scenario for OTel requirement otel-invocation-2. */ +public final class Otel2WaitResume extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "wait-resume"); + context.wait("otel-wait", Duration.ofSeconds(1)); + return context.step("otel-after-resume", String.class, step -> "resumed"); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel3Retry.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel3Retry.java new file mode 100644 index 000000000..347fc3565 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel3Retry.java @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.retry.RetryStrategies; + +/** Retried step scenario for OTel requirement otel-invocation-3. */ +public final class Otel3Retry extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "retry"); + return context.step( + "otel-retry", + String.class, + step -> { + if (step.getAttempt() < 2) { + throw new RuntimeException("Intentional first-attempt failure"); + } + return "retried"; + }, + StepConfig.builder() + .retryStrategy(RetryStrategies.fixedDelay(2, Duration.ofSeconds(1))) + .build()); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel4TerminalFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel4TerminalFailure.java new file mode 100644 index 000000000..a98ce9fc4 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel4TerminalFailure.java @@ -0,0 +1,26 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.retry.RetryStrategies; + +/** Terminal step failure scenario for OTel requirement otel-invocation-4. */ +public final class Otel4TerminalFailure extends OtelConformanceHandler { + + @Override + public Void handleRequest(Map event, DurableContext context) { + requireScenario(event, "terminal-failure"); + return context.step( + "otel-terminal-failure", + Void.class, + step -> { + throw new RuntimeException("Intentional terminal failure"); + }, + StepConfig.builder() + .retryStrategy(RetryStrategies.Presets.NO_RETRY) + .build()); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel5ChildContext.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel5ChildContext.java new file mode 100644 index 000000000..369e05d96 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel5ChildContext.java @@ -0,0 +1,19 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Child-context hierarchy scenario for OTel requirement otel-invocation-5. */ +public final class Otel5ChildContext extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "child-context"); + return context.runInChildContext( + "otel-child-context", + String.class, + child -> child.step("otel-child-step", String.class, step -> "child-complete")); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel6Parallel.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel6Parallel.java new file mode 100644 index 000000000..94ceb3fc5 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel6Parallel.java @@ -0,0 +1,33 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.List; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableFuture; +import software.amazon.lambda.durable.config.ParallelConfig; + +/** Parallel hierarchy scenario for OTel requirement otel-invocation-6. */ +public final class Otel6Parallel extends OtelConformanceHandler> { + + @Override + public List handleRequest(Map event, DurableContext context) { + requireScenario(event, "parallel-hierarchy"); + var parallel = context.parallel( + "otel-parallel", ParallelConfig.builder().maxConcurrency(1).build()); + DurableFuture branchA; + DurableFuture branchB; + try (parallel) { + branchA = parallel.branch( + "otel-parallel-branch-a", + String.class, + branch -> branch.step("otel-parallel-step-a", String.class, step -> "a")); + branchB = parallel.branch( + "otel-parallel-branch-b", + String.class, + branch -> branch.step("otel-parallel-step-b", String.class, step -> "b")); + } + return List.of(branchA.get(), branchB.get()); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel7Map.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel7Map.java new file mode 100644 index 000000000..cf4fbc426 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel7Map.java @@ -0,0 +1,25 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.List; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.MapConfig; + +/** Map hierarchy scenario for OTel requirement otel-invocation-7. */ +public final class Otel7Map extends OtelConformanceHandler> { + + @Override + public List handleRequest(Map event, DurableContext context) { + requireScenario(event, "map-hierarchy"); + return context.map( + "otel-map", + List.of(1, 2), + Integer.class, + (item, index, iteration) -> + iteration.step("otel-map-step-" + index, Integer.class, step -> item * 2), + MapConfig.builder().maxConcurrency(1).build()) + .results(); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel8HandledFailure.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel8HandledFailure.java new file mode 100644 index 000000000..932b65ee6 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel8HandledFailure.java @@ -0,0 +1,31 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.retry.RetryStrategies; + +/** Handled step failure scenario for OTel requirement otel-invocation-8. */ +public final class Otel8HandledFailure extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "handled-failure"); + try { + context.step( + "otel-handled-failure", + Void.class, + step -> { + throw new RuntimeException("Intentional handled failure"); + }, + StepConfig.builder() + .retryStrategy(RetryStrategies.Presets.NO_RETRY) + .build()); + } catch (RuntimeException expected) { + // Continue into the recovery step after recording the failed operation. + } + return context.step("otel-recovery-step", String.class, step -> "recovered"); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel9WaitForCondition.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel9WaitForCondition.java new file mode 100644 index 000000000..13d933d5e --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/Otel9WaitForCondition.java @@ -0,0 +1,32 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.WaitForConditionConfig; +import software.amazon.lambda.durable.model.WaitForConditionResult; +import software.amazon.lambda.durable.retry.WaitStrategies; + +/** Wait-for-condition scenario for OTel requirement otel-invocation-9. */ +public final class Otel9WaitForCondition extends OtelConformanceHandler { + + @Override + public Integer handleRequest(Map event, DurableContext context) { + requireScenario(event, "wait-for-condition"); + return context.waitForCondition( + "otel-condition", + Integer.class, + (state, step) -> { + var next = state + 1; + return next >= 2 + ? WaitForConditionResult.stopPolling(next) + : WaitForConditionResult.continuePolling(next); + }, + WaitForConditionConfig.builder() + .initialState(0) + .waitStrategy(WaitStrategies.fixedDelay(3, Duration.ofSeconds(1))) + .build()); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelConformanceHandler.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelConformanceHandler.java new file mode 100644 index 000000000..9c4bc01e3 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelConformanceHandler.java @@ -0,0 +1,60 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.math.BigDecimal; +import java.util.Map; +import software.amazon.lambda.durable.DurableConfig; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.otel.ExecutionOtelPlugin; +import software.amazon.lambda.durable.otel.InvocationOtelPlugin; +import software.amazon.lambda.durable.plugin.DurableExecutionPlugin; + +/** + * Shared base for the OTel conformance suite's handlers. Ported from the otel-invocation/otel-execution examples in + * aws/aws-durable-execution-conformance-tests. Each handler is deployed twice (see template.yaml): once for the + * otel-invocation suite (default, loads {@link InvocationOtelPlugin}) and once for the otel-execution suite (loads + * {@link ExecutionOtelPlugin} via the {@code OTEL_PLUGIN_MODE=execution} environment variable), against the X-Ray + * backend only. + */ +abstract class OtelConformanceHandler extends DurableHandler, O> { + + protected OtelConformanceHandler() { + super(new TypeToken>() {}); + } + + @Override + protected final DurableConfig createConfiguration() { + return DurableConfig.builder().withPlugins(createPlugin()).build(); + } + + private DurableExecutionPlugin createPlugin() { + return "execution".equals(System.getenv("OTEL_PLUGIN_MODE")) + ? new ExecutionOtelPlugin() + : new InvocationOtelPlugin(); + } + + protected final void requireScenario(Map event, String expected) { + var actual = event.get("scenario"); + if (!expected.equals(actual)) { + throw new IllegalArgumentException("Expected scenario " + expected + ", received " + actual); + } + } + + protected final long longDelaySeconds(Map event) { + var rawDelay = event.get("delay_seconds"); + final long delay; + try { + // longValueExact rejects fractional values (1.5) and anything outside long range, + // rather than silently truncating or wrapping them. + delay = new BigDecimal(String.valueOf(rawDelay)).longValueExact(); + } catch (ArithmeticException | NumberFormatException error) { + throw new IllegalArgumentException("delay_seconds must be an integer from 1 through 86400", error); + } + if (delay < 1 || delay > 86400) { + throw new IllegalArgumentException("delay_seconds must be an integer from 1 through 86400"); + } + return delay; + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning1Wait.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning1Wait.java new file mode 100644 index 000000000..46ed65907 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning1Wait.java @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Long durable wait for OTel requirement otel-long-running-1. */ +public final class OtelLongRunning1Wait extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "long-wait"); + context.wait("otel-long-wait", Duration.ofSeconds(longDelaySeconds(event))); + return context.step("otel-after-long-wait", String.class, step -> "resumed"); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning2Retry.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning2Retry.java new file mode 100644 index 000000000..e039e058d --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning2Retry.java @@ -0,0 +1,30 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.retry.RetryStrategies; + +/** Long retry delay for OTel requirement otel-long-running-2. */ +public final class OtelLongRunning2Retry extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "long-retry"); + return context.step( + "otel-long-retry", + String.class, + step -> { + if (step.getAttempt() < 2) { + throw new RuntimeException("Intentional first-attempt failure"); + } + return "retried"; + }, + StepConfig.builder() + .retryStrategy(RetryStrategies.fixedDelay(2, Duration.ofSeconds(longDelaySeconds(event)))) + .build()); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning3Callback.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning3Callback.java new file mode 100644 index 000000000..07c40b15f --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning3Callback.java @@ -0,0 +1,17 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Delayed callback for OTel requirement otel-long-running-3. */ +public final class OtelLongRunning3Callback extends OtelConformanceHandler { + + @Override + public String handleRequest(Map event, DurableContext context) { + requireScenario(event, "long-callback"); + longDelaySeconds(event); + return context.waitForCallback("otel-long-callback", String.class, (callbackId, step) -> {}); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4ChainedInvoke.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4ChainedInvoke.java new file mode 100644 index 000000000..74d0752d8 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4ChainedInvoke.java @@ -0,0 +1,21 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.TypeToken; + +/** Long chained invoke for OTel requirement otel-long-running-4. */ +public final class OtelLongRunning4ChainedInvoke extends OtelConformanceHandler> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + requireScenario(event, "long-chained-invoke"); + return context.invoke( + "otel-long-invoke", + System.getenv("OTEL_INVOKE_TARGET_FUNCTION_NAME"), + event, + new TypeToken>() {}); + } +} diff --git a/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4InvokeTarget.java b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4InvokeTarget.java new file mode 100644 index 000000000..cb3693367 --- /dev/null +++ b/conformance-tests-otel/src/main/java/software/amazon/lambda/durable/conformance/otel/OtelLongRunning4InvokeTarget.java @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +package software.amazon.lambda.durable.conformance.otel; + +import java.time.Duration; +import java.util.Map; +import software.amazon.lambda.durable.DurableContext; + +/** Delayed target for OTel requirement otel-long-running-4. */ +public final class OtelLongRunning4InvokeTarget extends OtelConformanceHandler> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + requireScenario(event, "long-chained-invoke"); + context.wait("otel-long-invoke-target-wait", Duration.ofSeconds(longDelaySeconds(event))); + return event; + } +} diff --git a/conformance-tests-otel/template-long-running.yaml b/conformance-tests-otel/template-long-running.yaml new file mode 100644 index 000000000..433dc4d24 --- /dev/null +++ b/conformance-tests-otel/template-long-running.yaml @@ -0,0 +1,110 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: > + Durable Execution Conformance Test Examples - Java (OTel, long-running suite). + Ported from the otel-long-running examples in aws/aws-durable-execution-conformance-tests. + otel-conformance-tests.yml only ever runs this in "short" mode (a real but brief 60-second + delay checked within one job, matching the same short-mode PR behavior JS/Python get from + the hosted orchestrator) -- not the full ~23-hour launch/check cycle used by the daily + scheduled run in that repo. + +Parameters: + LambdaExecutionRoleArn: + Type: String + Description: Pre-created execution role for the test functions + OtelLayerArn: + Type: String + Description: AWS Distro for OpenTelemetry Java Lambda layer + OtelExecWrapper: + Type: String + Default: /opt/otel-instrument + Description: OpenTelemetry Java agent execution wrapper + OtelServiceName: + Type: String + Default: durable-execution-conformance + Description: OpenTelemetry resource service name + OtelView: + Type: String + Default: invocation + AllowedValues: + - invocation + - execution + Description: OpenTelemetry plugin view used by the long-running functions + OtelTracesExporter: + Type: String + Default: otlp + Description: OpenTelemetry traces exporter selected by the runner + +Globals: + Function: + Runtime: java21 + Architectures: + - x86_64 + Timeout: 60 + MemorySize: 1024 + Tracing: Active + Layers: + - !Ref OtelLayerArn + DurableConfig: + ExecutionTimeout: 180000 + RetentionPeriodInDays: 3 + Environment: + Variables: + AWS_LAMBDA_EXEC_WRAPPER: !Ref OtelExecWrapper + JAVA_TOOL_OPTIONS: "-Dotel.javaagent.extensions=/var/task/lib/otel-plugin-extension.jar" + OTEL_JAVAAGENT_EXTENSIONS: /var/task/lib/otel-plugin-extension.jar + OTEL_SERVICE_NAME: !Ref OtelServiceName + OTEL_PLUGIN_MODE: !Ref OtelView + OTEL_TRACES_EXPORTER: !Ref OtelTracesExporter + OTEL_PROPAGATORS: xray + +Resources: + OtelLongRunning1Wait: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-long-running-1 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.OtelLongRunning1Wait + Role: !Ref LambdaExecutionRoleArn + + OtelLongRunning2Retry: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-long-running-2 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.OtelLongRunning2Retry + Role: !Ref LambdaExecutionRoleArn + + OtelLongRunning3Callback: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-long-running-3 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.OtelLongRunning3Callback + Role: !Ref LambdaExecutionRoleArn + + OtelLongRunning4ChainedInvoke: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-long-running-4 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.OtelLongRunning4ChainedInvoke + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_INVOKE_TARGET_FUNCTION_NAME: !Sub "${OtelLongRunning4InvokeTarget.Arn}:$LATEST" + + OtelLongRunning4InvokeTarget: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.OtelLongRunning4InvokeTarget + Role: !Ref LambdaExecutionRoleArn diff --git a/conformance-tests-otel/template.yaml b/conformance-tests-otel/template.yaml new file mode 100644 index 000000000..0ac9261f9 --- /dev/null +++ b/conformance-tests-otel/template.yaml @@ -0,0 +1,578 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: > + Durable Execution Conformance Test Examples - Java (OTel, invocation + execution views, + all backends). Ported from the otel-invocation/otel-execution examples in + aws/aws-durable-execution-conformance-tests: full suite (view) and backend parity with the + upstream Java example project (X-Ray, Dash0, Datadog, S3 collector), deployed as one stack + per backend by otel-conformance-tests.yml. + +Parameters: + LambdaExecutionRoleArn: + Type: String + Description: Pre-created execution role for the test functions + OtelLayerArn: + Type: String + Description: OpenTelemetry Lambda layer ARN (ADOT for X-Ray, community layer for Dash0/Datadog/collector) + OtelCollectorLayerArn: + Type: String + Default: "" + Description: Optional OpenTelemetry Collector Lambda extension layer (S3 collector backend only) + OtelCollectorBucket: + Type: String + Default: "" + Description: S3 bucket where the collector writes OTLP trace objects + OtelCollectorPrefix: + Type: String + Default: "" + Description: S3 key prefix where the collector writes OTLP trace objects + OtelExecWrapper: + Type: String + Default: /opt/otel-instrument + Description: OpenTelemetry Java agent execution wrapper + OtelServiceName: + Type: String + Default: durable-execution-conformance + Description: OpenTelemetry resource service name + OtelTracesExporter: + Type: String + Default: otlp + Description: OpenTelemetry traces exporter selected by the runner + OtelExporterEndpoint: + Type: String + Default: "" + Description: Non-secret OTLP endpoint used by community exporters (Dash0/Datadog/collector) + OtelExporterHeaders: + Type: String + Default: "" + NoEcho: true + Description: Secret OTLP exporter headers supplied by the runner (Dash0/Datadog) + +Conditions: + HasOtelCollectorLayer: !Not [!Equals [!Ref OtelCollectorLayerArn, ""]] + HasOtelExporterEndpoint: !Not [!Equals [!Ref OtelExporterEndpoint, ""]] + HasOtelExporterHeaders: !Not [!Equals [!Ref OtelExporterHeaders, ""]] + +Globals: + Function: + Runtime: java21 + Architectures: + - x86_64 + Timeout: 60 + MemorySize: 1024 + Tracing: Active + Layers: !If + - HasOtelCollectorLayer + - [!Ref OtelLayerArn, !Ref OtelCollectorLayerArn] + - [!Ref OtelLayerArn] + DurableConfig: + ExecutionTimeout: 300 + RetentionPeriodInDays: 1 + Environment: + Variables: + AWS_LAMBDA_EXEC_WRAPPER: !Ref OtelExecWrapper + JAVA_TOOL_OPTIONS: "-Dotel.javaagent.extensions=/var/task/lib/otel-plugin-extension.jar" + OTEL_JAVAAGENT_EXTENSIONS: /var/task/lib/otel-plugin-extension.jar + OTEL_SERVICE_NAME: !Ref OtelServiceName + OTEL_TRACES_EXPORTER: !Ref OtelTracesExporter + OTEL_EXPORTER_OTLP_ENDPOINT: !If + - HasOtelExporterEndpoint + - !Ref OtelExporterEndpoint + - !Ref "AWS::NoValue" + OTEL_EXPORTER_OTLP_HEADERS: !If + - HasOtelExporterHeaders + - !Ref OtelExporterHeaders + - !Ref "AWS::NoValue" + OTEL_EXPORTER_OTLP_PROTOCOL: !If [HasOtelExporterEndpoint, http/protobuf, grpc] + OTEL_PROPAGATORS: xray + OTEL_S3_BUCKET: !Ref OtelCollectorBucket + OTEL_S3_PREFIX: !Ref OtelCollectorPrefix + OPENTELEMETRY_COLLECTOR_CONFIG_URI: !If + - HasOtelCollectorLayer + - /opt/collector-config/config-s3.yaml + - !Ref "AWS::NoValue" + +Resources: + Otel1Success: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-1 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel1Success + Role: !Ref LambdaExecutionRoleArn + + Otel2WaitResume: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-2 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel2WaitResume + Role: !Ref LambdaExecutionRoleArn + + Otel3Retry: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-3 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel3Retry + Role: !Ref LambdaExecutionRoleArn + + Otel4TerminalFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-4 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel4TerminalFailure + Role: !Ref LambdaExecutionRoleArn + + Otel5ChildContext: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-5 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel5ChildContext + Role: !Ref LambdaExecutionRoleArn + + Otel6Parallel: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-6 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel6Parallel + Role: !Ref LambdaExecutionRoleArn + + Otel7Map: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-7 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel7Map + Role: !Ref LambdaExecutionRoleArn + + Otel8HandledFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-8 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel8HandledFailure + Role: !Ref LambdaExecutionRoleArn + + Otel9WaitForCondition: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-9 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel9WaitForCondition + Role: !Ref LambdaExecutionRoleArn + + Otel10WaitForCallback: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-10 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel10WaitForCallback + Role: !Ref LambdaExecutionRoleArn + + Otel11ChainedInvoke: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-11 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel11ChainedInvoke + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_INVOKE_TARGET_FUNCTION_NAME: !Sub "${Otel11InvokeTarget.Arn}:$LATEST" + + Otel11InvokeTarget: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel11InvokeTarget + Role: !Ref LambdaExecutionRoleArn + + Otel12ChildContextFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-12 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel12ChildContextFailure + Role: !Ref LambdaExecutionRoleArn + + Otel13ParallelFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-13 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel13ParallelFailure + Role: !Ref LambdaExecutionRoleArn + + Otel14MapFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-14 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel14MapFailure + Role: !Ref LambdaExecutionRoleArn + + Otel15WaitInterrupted: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-15 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel15WaitInterrupted + Role: !Ref LambdaExecutionRoleArn + DurableConfig: + ExecutionTimeout: 15 + RetentionPeriodInDays: 1 + + Otel16WaitForConditionFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-16 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel16WaitForConditionFailure + Role: !Ref LambdaExecutionRoleArn + + Otel17WaitForCallbackFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-17 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel17WaitForCallbackFailure + Role: !Ref LambdaExecutionRoleArn + + Otel18ChainedInvokeFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-18 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel18ChainedInvokeFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_INVOKE_TARGET_FUNCTION_NAME: !Sub "${Otel18InvokeTarget.Arn}:$LATEST" + + Otel18InvokeTarget: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel18InvokeTarget + Role: !Ref LambdaExecutionRoleArn + + Otel19ExecutionFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-invocation-19 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel19ExecutionFailure + Role: !Ref LambdaExecutionRoleArn + OtelExecution1Success: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-1 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel1Success + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution2WaitResume: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-2 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel2WaitResume + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution3Retry: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-3 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel3Retry + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution4TerminalFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-4 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel4TerminalFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution5ChildContext: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-5 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel5ChildContext + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution6Parallel: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-6 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel6Parallel + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution7Map: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-7 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel7Map + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution8HandledFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-8 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel8HandledFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution9WaitForCondition: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-9 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel9WaitForCondition + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution10WaitForCallback: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-10 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel10WaitForCallback + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution11ChainedInvoke: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-11 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel11ChainedInvoke + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + OTEL_INVOKE_TARGET_FUNCTION_NAME: !Sub "${OtelExecution11InvokeTarget.Arn}:$LATEST" + + OtelExecution11InvokeTarget: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel11InvokeTarget + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution12ChildContextFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-12 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel12ChildContextFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution13ParallelFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-13 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel13ParallelFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution14MapFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-14 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel14MapFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution15WaitInterrupted: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-15 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel15WaitInterrupted + Role: !Ref LambdaExecutionRoleArn + DurableConfig: + ExecutionTimeout: 15 + RetentionPeriodInDays: 1 + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution16WaitForConditionFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-16 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel16WaitForConditionFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution17WaitForCallbackFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-17 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel17WaitForCallbackFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution18ChainedInvokeFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-18 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel18ChainedInvokeFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + OTEL_INVOKE_TARGET_FUNCTION_NAME: !Sub "${OtelExecution18InvokeTarget.Arn}:$LATEST" + + OtelExecution18InvokeTarget: + Type: AWS::Serverless::Function + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel18InvokeTarget + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution + + OtelExecution19ExecutionFailure: + Type: AWS::Serverless::Function + TestingMetadata: + TestDescription: + - otel-execution-19 + Properties: + CodeUri: . + Handler: software.amazon.lambda.durable.conformance.otel.Otel19ExecutionFailure + Role: !Ref LambdaExecutionRoleArn + Environment: + Variables: + OTEL_PLUGIN_MODE: execution From f28b9a3401310d51b5b7f67e4d339d02abb5100e Mon Sep 17 00:00:00 2001 From: Ayushi Ahjolia Date: Tue, 18 Aug 2026 15:00:00 -0700 Subject: [PATCH 2/2] Update .github/workflows/otel-conformance-tests.yml Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .github/workflows/otel-conformance-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/otel-conformance-tests.yml b/.github/workflows/otel-conformance-tests.yml index d32843582..568b6db50 100644 --- a/.github/workflows/otel-conformance-tests.yml +++ b/.github/workflows/otel-conformance-tests.yml @@ -65,7 +65,7 @@ jobs: resource_prefix: j sdk_repository: aws/aws-durable-execution-sdk-java sdk_ref: ${{ github.event.pull_request.head.sha || github.sha }} - conformance_test_ref: ${{ inputs.conformance_test_ref || 'main' }} + conformance_test_ref: ${{ inputs.conformance_test_ref || '0f0b5bda84116ef77034451b9c4c21774e76d8e4' }} checkout_sdk: true # Build the handlers from this repo's checked-out module instead of the conformance repo's # bundled examples/java. Path is relative to the conformance workspace where the SDK is