Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions conformance-tests-telemetry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Durable Execution Java SDK — Durable Execution Telemetry Conformance Tests

This module answers one question. Does the telemetry exporter (`aws-durable-execution-sdk-java-plugin-telemetry-exporter`),
with its `CloudWatchLogsExporter`, deliver a complete `DurableExecutionTelemetry` record to CloudWatch Logs for a real
Lambda execution?

Unit tests can assert that the plugin builds a record. They cannot assert that the record reaches the configured log
group on a real invocation or that it carries the right identity fields for the deployed function. Those are properties
of a deployed function. So the scenario here is a Lambda function. The runner deploys it with the plugin configured,
invokes it once, fetches the record from CloudWatch Logs, and checks it against the requirement.

The requirement and the runner live in
[`aws/aws-durable-execution-conformance-tests`](https://github.com/aws/aws-durable-execution-conformance-tests), package
`aws-durable-execution-conformance-tests-telemetry`. This module holds the SDK-specific part: the handler and the SAM
template that maps it to the requirement ID.

## Coverage

| Suite | Requirement | What it pins down |
| ----------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `telemetry` | `telemetry-1` | One successful single-step execution emits one `SUCCEEDED` record with `input`, `output`, ARN-derived identity fields, and `operationsByName`. |

## Layout

```
pom.xml # standalone Maven project (not a reactor module)
template.yaml # telemetry suite; declares TelemetryLogGroupName and creates the group
src/main/java/software/amazon/lambda/durable/conformance/telemetry/
Telemetry1Success.java # single step "increment"; plugin + CloudWatchLogsExporter
```

The handler uses the real SDK API only. It constructs no record and calls no exporter method. A missing or wrong record
is the plugin's defect. That defect is the signal the suite measures.

The handler configuration is: one `CloudWatchLogsExporter`, emit mode `ON_COMPLETE`, sampling rate 1, operation detail
`TOP_LEVEL`, and content input and output enabled.

## Template contract

The runner passes `TelemetryLogGroupName`. Extensions have no pre-deploy hook, so the template creates the group with an
`AWS::Logs::LogGroup` resource, and the function depends on it. The group name reaches the handler through
`TELEMETRY_LOG_GROUP_NAME`. The handler fails at class initialization when that variable is unset.

The `LambdaExecutionRoleArn` role must allow `logs:CreateLogStream` and `logs:PutLogEvents` on the group.
`AWSLambdaBasicDurableExecutionRolePolicy` grants both on `*`.

## Building locally

Prerequisites: JDK 17 or later, Maven, and the AWS SAM CLI.
Comment thread
hln33 marked this conversation as resolved.
Comment thread
hln33 marked this conversation as resolved.

```bash
# from the repository root: install the SDK and the telemetry exporter to the local Maven repository
mvn -B -q -Dmaven.test.skip=true install

# tell this module which SDK version to build against (the root pom version)
export JAVA_SDK_VERSION=$(mvn -q help:evaluate -Dexpression=project.version -DforceStdout)

cd conformance-tests-telemetry
sam build
```

The pom reads the SDK version from `JAVA_SDK_VERSION` through the `durable.sdk.version` property. The exporter declares
`cloudwatchlogs` as optional, so this module declares it directly.

Cloud run, from a checkout of the conformance repository with the telemetry package installed:

```bash
durable-execution-conformance \
--template <this-repo>/conformance-tests-telemetry/template.yaml \
--language java --region us-west-2 --suite telemetry \
--report console json \
--parameter-overrides LambdaExecutionRoleArn=<role-arn>
```

A caller GitHub workflow is a follow-on.
94 changes: 94 additions & 0 deletions conformance-tests-telemetry/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<!--
Standalone project (NOT part of the SDK reactor): the Durable Execution Telemetry
conformance run builds this module against an SDK already installed to the local
repository. The SDK version comes from the JAVA_SDK_VERSION environment variable through
the durable.sdk.version property. SAM builds the same pom during deploy.
The module depends on the SDK and telemetry-exporter artifacts by version, not as
reactor siblings. The exporter declares the CloudWatch Logs client as optional,
so this module declares it directly.
-->
<groupId>software.amazon.lambda.durable</groupId>
<artifactId>aws-durable-execution-sdk-java-conformance-tests-telemetry</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>AWS Lambda Durable Execution SDK Telemetry Conformance Tests</name>
<description>
Java SDK handlers and SAM template for the Durable Execution Telemetry conformance
suite (telemetry-1).
</description>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.release>17</maven.compiler.release>
<!-- Supplied by the conformance workflow (JAVA_SDK_VERSION), resolved from the built SDK. -->
<durable.sdk.version>${env.JAVA_SDK_VERSION}</durable.sdk.version>
<aws.sdk.version>2.56.0</aws.sdk.version>
<aws.lambda.java.core.version>1.4.1</aws.lambda.java.core.version>
</properties>

<dependencies>
<dependency>
<groupId>software.amazon.lambda.durable</groupId>
<artifactId>aws-durable-execution-sdk-java</artifactId>
<version>${durable.sdk.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.lambda.durable</groupId>
<artifactId>aws-durable-execution-sdk-java-plugin-telemetry-exporter</artifactId>
<version>${durable.sdk.version}</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>cloudwatchlogs</artifactId>
<version>${aws.sdk.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>${aws.lambda.java.core.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.15.0</version>
</plugin>

<!-- Shaded (uber) JAR so the Lambda deploys as a single artifact. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.conformance.telemetry;

import software.amazon.lambda.durable.DurableConfig;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
import software.amazon.lambda.durable.telemetry.ContentConfig;
import software.amazon.lambda.durable.telemetry.DurableExecutionTelemetry;
import software.amazon.lambda.durable.telemetry.DurableExecutionTelemetryConfig;
import software.amazon.lambda.durable.telemetry.exporters.CloudWatchLogsExporter;

/**
* Single successful step scenario for requirement telemetry-1.
*
* <p>The handler configures the telemetry plugin with one CloudWatch Logs exporter. It constructs no record and calls
* no exporter method. The plugin builds and exports the record.
*/
public final class Telemetry1Success extends DurableHandler<Telemetry1Success.Input, Telemetry1Success.Output> {

// The deployed function must export to the log group the runner reads.
// A missing variable would produce a function that exports nowhere.
// So class initialization fails when the variable is unset.
private static final String LOG_GROUP_NAME = System.getenv("TELEMETRY_LOG_GROUP_NAME");

static {
if (LOG_GROUP_NAME == null || LOG_GROUP_NAME.isBlank()) {
throw new IllegalStateException("TELEMETRY_LOG_GROUP_NAME must be set");
}
}

@Override
protected DurableConfig createConfiguration() {
return DurableConfig.builder()
.withPlugins(DurableExecutionTelemetry.durableExecutionTelemetry(
DurableExecutionTelemetryConfig.builder()
.addExporter(CloudWatchLogsExporter.builder()
.logGroupName(LOG_GROUP_NAME)
.build())
.emitMode(DurableExecutionTelemetryConfig.EmitMode.ON_COMPLETE)
.samplingRate(1.0)
.operationDetail(DurableExecutionTelemetryConfig.OperationDetail.TOP_LEVEL)
.content(ContentConfig.builder()
.input(true)
.output(true)
.build())
.build()))
.build();
}

@Override
public Output handleRequest(Input input, DurableContext context) {
int value = context.step("increment", Integer.class, step -> input.value + 1);
return new Output(value);
}

/** Event payload: {"value": 41}. */
public static final class Input {
public int value;

public Input() {}
}

/** Result payload: {"value": 42}. */
public static final class Output {
public int value;

public Output() {}

public Output(int value) {
this.value = value;
}
}
}
45 changes: 45 additions & 0 deletions conformance-tests-telemetry/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Java SDK examples for the Durable Execution Telemetry conformance suite

Parameters:
LambdaExecutionRoleArn:
Type: String
Description: Pre-created execution role for the test functions
TelemetryLogGroupName:
Type: String
Description: CloudWatch Logs group that receives Durable Execution Telemetry records

Globals:
Function:
Runtime: java21
Architectures:
- x86_64
Timeout: 60
MemorySize: 1024
DurableConfig:
ExecutionTimeout: 300
RetentionPeriodInDays: 1
Environment:
Variables:
TELEMETRY_LOG_GROUP_NAME: !Ref TelemetryLogGroupName

Resources:
# Extensions have no pre-deploy hook, so CloudFormation creates the group
# before the runner invokes any function.
TelemetryLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Ref TelemetryLogGroupName
RetentionInDays: 1

Telemetry1Success:
Type: AWS::Serverless::Function
DependsOn: TelemetryLogGroup
TestingMetadata:
TestDescription:
- telemetry-1
Properties:
CodeUri: .
Handler: software.amazon.lambda.durable.conformance.telemetry.Telemetry1Success
Role: !Ref LambdaExecutionRoleArn
Loading