Skip to content

Commit

Permalink
Merge pull request #617 from hjgraca/example-update-release-1.11.1
Browse files Browse the repository at this point in the history
chore: update examples for release 1.11.1
  • Loading branch information
hjgraca authored Jul 12, 2024
2 parents a1ae03a + 013f376 commit cbb2d72
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 2 deletions.
25 changes: 25 additions & 0 deletions examples/AOT/src/AOT/AOT.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AWSProjectType>Lambda</AWSProjectType>
<!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<!-- Generate Native AOT image during publishing to improve cold start time. -->
<PublishAot>true</PublishAot>
<!-- StripSymbols tells the compiler to strip debugging symbols from the final executable if we're on Linux and put them into their own file.
This will greatly reduce the final executable's size.-->
<StripSymbols>true</StripSymbols>
<!-- TrimMode partial will only trim assemblies marked as trimmable. To reduce package size make all assemblies trimmable and set TrimMode to full.
If there are trim warnings during build, you can hit errors at runtime.-->
<TrimMode>partial</TrimMode>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.RuntimeSupport" Version="1.10.0"/>
<PackageReference Include="Amazon.Lambda.Core" Version="2.2.0"/>
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.1"/>
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.7.1" />
</ItemGroup>
</Project>
81 changes: 81 additions & 0 deletions examples/AOT/src/AOT/Function.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport;
using Amazon.Lambda.Serialization.SystemTextJson;
using System.Text.Json.Serialization;
using AWS.Lambda.Powertools.Metrics;

namespace AOT;

public class Function
{
/// <summary>
/// The main entry point for the Lambda function. The main function is called once during the Lambda init phase. It
/// initializes the .NET Lambda runtime client passing in the function handler to invoke for each Lambda event and
/// the JSON serializer to use for converting Lambda JSON format to the .NET types.
/// </summary>
private static async Task Main()
{
Func<string, ILambdaContext, string> handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler,
new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>())
.Build()
.RunAsync();
}

/// <summary>
/// A simple function that takes a string and does a ToUpper.
///
/// To use this handler to respond to an AWS event, reference the appropriate package from
/// https://github.com/aws/aws-lambda-dotnet#events
/// and change the string input parameter to the desired event type. When the event type
/// is changed, the handler type registered in the main method needs to be updated and the LambdaFunctionJsonSerializerContext
/// defined below will need the JsonSerializable updated. If the return type and event type are different then the
/// LambdaFunctionJsonSerializerContext must have two JsonSerializable attributes, one for each type.
///
// When using Native AOT extra testing with the deployed Lambda functions is required to ensure
// the libraries used in the Lambda function work correctly with Native AOT. If a runtime
// error occurs about missing types or methods the most likely solution will be to remove references to trim-unsafe
// code or configure trimming options. This sample defaults to partial TrimMode because currently the AWS
// SDK for .NET does not support trimming. This will result in a larger executable size, and still does not
// guarantee runtime trimming errors won't be hit.
/// </summary>
/// <param name="input">The event for the Lambda function handler to process.</param>
/// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
/// <returns></returns>

// You can optionally capture cold start metrics by setting CaptureColdStart parameter to true.
[Metrics(Namespace = "ns", Service = "svc", CaptureColdStart = true)]
public static string FunctionHandler(string input, ILambdaContext context)
{
// You can create metrics using AddMetric
// MetricUnit enum facilitates finding a supported metric unit by CloudWatch.
Metrics.AddMetric("Handler invocation", 1, MetricUnit.Count);
return ToUpper(input);
}

private static string ToUpper(string input)
{
Metrics.AddMetric("ToUpper invocation", 1, MetricUnit.Count);

var upper = input.ToUpper();

// You can add high-cardinality data as part of your Metrics log with AddMetadata method.
// This is useful when you want to search highly contextual information along with your metrics in your logs.
Metrics.AddMetadata("Input Uppercase", upper);

return upper;
}
}

/// <summary>
/// This class is used to register the input event and return type for the FunctionHandler method with the System.Text.Json source generator.
/// There must be a JsonSerializable attribute for each type used as the input and return type or a runtime error will occur
/// from the JSON serializer unable to find the serialization information for unknown types.
/// </summary>
[JsonSerializable(typeof(string))]
public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext
{
// By using this partial class derived from JsonSerializerContext, we can generate reflection free JSON Serializer code at compile time
// which can deserialize our class and properties. However, we must attribute this class to tell it what types to generate serialization code for.
// See https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation
}
82 changes: 82 additions & 0 deletions examples/AOT/src/AOT/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# AWS Lambda Native AOT Project with Powertools for AWS Lambda (.NET)

This starter project consists of:
* Function.cs - contains a class with a `Main` method that starts the bootstrap and a single function handler method.
* aws-lambda-tools-defaults.json - default argument settings for use with Visual Studio and command line deployment tools for AWS.

You may also have a test project depending on the options selected.

The `Main` function is called once during the Lambda init phase. It initializes the .NET Lambda runtime client passing in the function
handler to invoke for each Lambda event and the JSON serializer to use for converting Lambda JSON format to the .NET types.

The function handler is a simple method accepting a string argument that returns the uppercase equivalent of the input string. Replace the body of this method and its parameters to suit your needs.

## Native AOT

Native AOT is a feature that compiles .NET assemblies into a single native executable. By using the native executable the .NET runtime
is not required to be installed on the target platform. Native AOT can significantly improve Lambda cold starts for .NET Lambda functions.
This project enables Native AOT by setting the .NET `PublishAot` property in the .NET project file to `true`. The `StripSymbols` property is also
set to `true` to strip debugging symbols from the deployed executable to reduce the executable's size.

### Building Native AOT

When publishing with Native AOT the build OS and Architecture must match the target platform that the application will run. For AWS Lambda that target
platform is Amazon Linux 2023. The AWS tooling for Lambda like the AWS Toolkit for Visual Studio, .NET Global Tool Amazon.Lambda.Tools and SAM CLI will
perform a container build using a .NET 8 Amazon Linux 2023 build image when `PublishAot` is set to `true`. This means **docker is a requirement**
when packaging .NET Native AOT Lambda functions on non-Amazon Linux 2023 build environments. To install docker go to https://www.docker.com/.

### Trimming

As part of the Native AOT compilation, .NET assemblies will be trimmed removing types and methods that the compiler does not find a reference to. This is important
to keep the native executable size small. When types are used through reflection this can go undetected by the compiler causing necessary types and methods to
be removed. When testing Native AOT Lambda functions in Lambda if a runtime error occurs about missing types or methods the most likely solution will
be to remove references to trim-unsafe code or configure [trimming options](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options).
This sample defaults to partial TrimMode because currently the AWS SDK for .NET does not support trimming. This will result in a larger executable size, and still does not
guarantee runtime trimming errors won't be hit.

For information about trimming see the documentation: <https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained>

## Docker requirement

Docker is required to be installed and running when building .NET Native AOT Lambda functions on any platform besides Amazon Linux 2023. Information on how acquire Docker can be found here: https://docs.docker.com/get-docker/

## Here are some steps to follow from Visual Studio:

To deploy your function to AWS Lambda, right click the project in Solution Explorer and select *Publish to AWS Lambda*.

To view your deployed function open its Function View window by double-clicking the function name shown beneath the AWS Lambda node in the AWS Explorer tree.

To perform testing against your deployed function use the Test Invoke tab in the opened Function View window.

To configure event sources for your deployed function, for example to have your function invoked when an object is created in an Amazon S3 bucket, use the Event Sources tab in the opened Function View window.

To update the runtime configuration of your deployed function use the Configuration tab in the opened Function View window.

To view execution logs of invocations of your function use the Logs tab in the opened Function View window.

## Here are some steps to follow to get started from the command line:

Once you have edited your template and code you can deploy your application using the [Amazon.Lambda.Tools Global Tool](https://github.com/aws/aws-extensions-for-dotnet-cli#aws-lambda-amazonlambdatools) from the command line. Version 5.6.0
or later is required to deploy this project.

Install Amazon.Lambda.Tools Global Tools if not already installed.
```
dotnet tool install -g Amazon.Lambda.Tools
```

If already installed check if new version is available.
```
dotnet tool update -g Amazon.Lambda.Tools
```

Execute unit tests
```
cd "AOT/test/AOT.Tests"
dotnet test
```

Deploy function to AWS Lambda
```
cd "AOT/src/AOT"
dotnet lambda deploy-function
```
16 changes: 16 additions & 0 deletions examples/AOT/src/AOT/aws-lambda-tools-defaults.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"Information": [
"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
"dotnet lambda help",
"All the command line options for the Lambda command can be specified in this file."
],
"profile": "",
"region": "",
"configuration": "Release",
"function-runtime": "dotnet8",
"function-memory-size": 512,
"function-timeout": 30,
"function-handler": "AOT",
"msbuild-parameters": "--self-contained true"
}
18 changes: 18 additions & 0 deletions examples/AOT/test/AOT.Tests/AOT.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="2.2.0" />
<PackageReference Include="Amazon.Lambda.TestUtilities" Version="2.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\AOT\AOT.csproj" />
</ItemGroup>
</Project>
18 changes: 18 additions & 0 deletions examples/AOT/test/AOT.Tests/FunctionTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Xunit;
using Amazon.Lambda.Core;
using Amazon.Lambda.TestUtilities;

namespace AOT.Tests;

public class FunctionTest
{
[Fact]
public void TestToUpperFunction()
{
// Invoke the lambda function and confirm the string was upper cased.
var context = new TestLambdaContext();
var upperCase = Function.FunctionHandler("hello world", context);

Assert.Equal("HELLO WORLD", upperCase);
}
}
2 changes: 1 addition & 1 deletion examples/Metrics/src/HelloWorld/HelloWorld.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.7.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.1" />
<PackageReference Include="AWS.Lambda.Powertools.Logging" Version="1.5.1" />
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.6.2" />
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.7.1" />
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.301.18" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<ItemGroup>
<PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="9.0.0" />
<PackageReference Include="AWS.Lambda.Powertools.Logging" Version="1.5.1" />
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.6.2" />
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.7.1" />
<PackageReference Include="AWS.Lambda.Powertools.Tracing" Version="1.4.2" />
</ItemGroup>
</Project>
22 changes: 22 additions & 0 deletions examples/examples.sln
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CE5C821F-5
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld.Tests", "BatchProcessing\test\HelloWorld.Test\HelloWorld.Tests.csproj", "{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AOT", "AOT", "{F622EDE4-15EB-4F30-AC63-68E848377F1D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C765423A-C454-4ABA-B39D-0B527F9BA09A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E04644BA-719E-40D9-AF91-DA6D412059C7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOT", "AOT\src\AOT\AOT.csproj", "{0E9D6881-9B32-47C5-89CC-299754D3FD88}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOT.Tests", "AOT\test\AOT.Tests\AOT.Tests.csproj", "{489F6927-B761-4F11-B8A6-BBD848281698}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -146,6 +156,14 @@ Global
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}.Release|Any CPU.Build.0 = Release|Any CPU
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Release|Any CPU.Build.0 = Release|Any CPU
{489F6927-B761-4F11-B8A6-BBD848281698}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{489F6927-B761-4F11-B8A6-BBD848281698}.Debug|Any CPU.Build.0 = Debug|Any CPU
{489F6927-B761-4F11-B8A6-BBD848281698}.Release|Any CPU.ActiveCfg = Release|Any CPU
{489F6927-B761-4F11-B8A6-BBD848281698}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0CC66DBC-C1DF-4AF6-8EEB-FFED6C578BF4} = {526F1EF7-5A9C-4BFF-ABAE-75992ACD8F78}
Expand Down Expand Up @@ -178,5 +196,9 @@ Global
{F33D0918-452F-4AB0-B842-E43AFE6F948D} = {B95EAACA-FBE4-4CC0-B155-D0AD9BCDEE24}
{CE5C821F-5610-490F-B096-EE91F0E34C10} = {2B5E8DE7-8DA4-47B8-81B7-9E269CC77619}
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88} = {CE5C821F-5610-490F-B096-EE91F0E34C10}
{C765423A-C454-4ABA-B39D-0B527F9BA09A} = {F622EDE4-15EB-4F30-AC63-68E848377F1D}
{E04644BA-719E-40D9-AF91-DA6D412059C7} = {F622EDE4-15EB-4F30-AC63-68E848377F1D}
{0E9D6881-9B32-47C5-89CC-299754D3FD88} = {C765423A-C454-4ABA-B39D-0B527F9BA09A}
{489F6927-B761-4F11-B8A6-BBD848281698} = {E04644BA-719E-40D9-AF91-DA6D412059C7}
EndGlobalSection
EndGlobal

0 comments on commit cbb2d72

Please sign in to comment.