Skip to content

Commit cbb2d72

Browse files
authored
Merge pull request #617 from hjgraca/example-update-release-1.11.1
chore: update examples for release 1.11.1
2 parents a1ae03a + 013f376 commit cbb2d72

File tree

9 files changed

+264
-2
lines changed

9 files changed

+264
-2
lines changed

examples/AOT/src/AOT/AOT.csproj

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
<AWSProjectType>Lambda</AWSProjectType>
8+
<!-- This property makes the build directory similar to a publish directory and helps the AWS .NET Lambda Mock Test Tool find project dependencies. -->
9+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
10+
<!-- Generate Native AOT image during publishing to improve cold start time. -->
11+
<PublishAot>true</PublishAot>
12+
<!-- StripSymbols tells the compiler to strip debugging symbols from the final executable if we're on Linux and put them into their own file.
13+
This will greatly reduce the final executable's size.-->
14+
<StripSymbols>true</StripSymbols>
15+
<!-- TrimMode partial will only trim assemblies marked as trimmable. To reduce package size make all assemblies trimmable and set TrimMode to full.
16+
If there are trim warnings during build, you can hit errors at runtime.-->
17+
<TrimMode>partial</TrimMode>
18+
</PropertyGroup>
19+
<ItemGroup>
20+
<PackageReference Include="Amazon.Lambda.RuntimeSupport" Version="1.10.0"/>
21+
<PackageReference Include="Amazon.Lambda.Core" Version="2.2.0"/>
22+
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.1"/>
23+
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.7.1" />
24+
</ItemGroup>
25+
</Project>

examples/AOT/src/AOT/Function.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using Amazon.Lambda.Core;
2+
using Amazon.Lambda.RuntimeSupport;
3+
using Amazon.Lambda.Serialization.SystemTextJson;
4+
using System.Text.Json.Serialization;
5+
using AWS.Lambda.Powertools.Metrics;
6+
7+
namespace AOT;
8+
9+
public class Function
10+
{
11+
/// <summary>
12+
/// The main entry point for the Lambda function. The main function is called once during the Lambda init phase. It
13+
/// initializes the .NET Lambda runtime client passing in the function handler to invoke for each Lambda event and
14+
/// the JSON serializer to use for converting Lambda JSON format to the .NET types.
15+
/// </summary>
16+
private static async Task Main()
17+
{
18+
Func<string, ILambdaContext, string> handler = FunctionHandler;
19+
await LambdaBootstrapBuilder.Create(handler,
20+
new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>())
21+
.Build()
22+
.RunAsync();
23+
}
24+
25+
/// <summary>
26+
/// A simple function that takes a string and does a ToUpper.
27+
///
28+
/// To use this handler to respond to an AWS event, reference the appropriate package from
29+
/// https://github.com/aws/aws-lambda-dotnet#events
30+
/// and change the string input parameter to the desired event type. When the event type
31+
/// is changed, the handler type registered in the main method needs to be updated and the LambdaFunctionJsonSerializerContext
32+
/// defined below will need the JsonSerializable updated. If the return type and event type are different then the
33+
/// LambdaFunctionJsonSerializerContext must have two JsonSerializable attributes, one for each type.
34+
///
35+
// When using Native AOT extra testing with the deployed Lambda functions is required to ensure
36+
// the libraries used in the Lambda function work correctly with Native AOT. If a runtime
37+
// error occurs about missing types or methods the most likely solution will be to remove references to trim-unsafe
38+
// code or configure trimming options. This sample defaults to partial TrimMode because currently the AWS
39+
// SDK for .NET does not support trimming. This will result in a larger executable size, and still does not
40+
// guarantee runtime trimming errors won't be hit.
41+
/// </summary>
42+
/// <param name="input">The event for the Lambda function handler to process.</param>
43+
/// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
44+
/// <returns></returns>
45+
46+
// You can optionally capture cold start metrics by setting CaptureColdStart parameter to true.
47+
[Metrics(Namespace = "ns", Service = "svc", CaptureColdStart = true)]
48+
public static string FunctionHandler(string input, ILambdaContext context)
49+
{
50+
// You can create metrics using AddMetric
51+
// MetricUnit enum facilitates finding a supported metric unit by CloudWatch.
52+
Metrics.AddMetric("Handler invocation", 1, MetricUnit.Count);
53+
return ToUpper(input);
54+
}
55+
56+
private static string ToUpper(string input)
57+
{
58+
Metrics.AddMetric("ToUpper invocation", 1, MetricUnit.Count);
59+
60+
var upper = input.ToUpper();
61+
62+
// You can add high-cardinality data as part of your Metrics log with AddMetadata method.
63+
// This is useful when you want to search highly contextual information along with your metrics in your logs.
64+
Metrics.AddMetadata("Input Uppercase", upper);
65+
66+
return upper;
67+
}
68+
}
69+
70+
/// <summary>
71+
/// This class is used to register the input event and return type for the FunctionHandler method with the System.Text.Json source generator.
72+
/// There must be a JsonSerializable attribute for each type used as the input and return type or a runtime error will occur
73+
/// from the JSON serializer unable to find the serialization information for unknown types.
74+
/// </summary>
75+
[JsonSerializable(typeof(string))]
76+
public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext
77+
{
78+
// By using this partial class derived from JsonSerializerContext, we can generate reflection free JSON Serializer code at compile time
79+
// which can deserialize our class and properties. However, we must attribute this class to tell it what types to generate serialization code for.
80+
// See https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-source-generation
81+
}

examples/AOT/src/AOT/Readme.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# AWS Lambda Native AOT Project with Powertools for AWS Lambda (.NET)
2+
3+
This starter project consists of:
4+
* Function.cs - contains a class with a `Main` method that starts the bootstrap and a single function handler method.
5+
* aws-lambda-tools-defaults.json - default argument settings for use with Visual Studio and command line deployment tools for AWS.
6+
7+
You may also have a test project depending on the options selected.
8+
9+
The `Main` function is called once during the Lambda init phase. It initializes the .NET Lambda runtime client passing in the function
10+
handler to invoke for each Lambda event and the JSON serializer to use for converting Lambda JSON format to the .NET types.
11+
12+
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.
13+
14+
## Native AOT
15+
16+
Native AOT is a feature that compiles .NET assemblies into a single native executable. By using the native executable the .NET runtime
17+
is not required to be installed on the target platform. Native AOT can significantly improve Lambda cold starts for .NET Lambda functions.
18+
This project enables Native AOT by setting the .NET `PublishAot` property in the .NET project file to `true`. The `StripSymbols` property is also
19+
set to `true` to strip debugging symbols from the deployed executable to reduce the executable's size.
20+
21+
### Building Native AOT
22+
23+
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
24+
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
25+
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**
26+
when packaging .NET Native AOT Lambda functions on non-Amazon Linux 2023 build environments. To install docker go to https://www.docker.com/.
27+
28+
### Trimming
29+
30+
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
31+
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
32+
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
33+
be to remove references to trim-unsafe code or configure [trimming options](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options).
34+
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
35+
guarantee runtime trimming errors won't be hit.
36+
37+
For information about trimming see the documentation: <https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained>
38+
39+
## Docker requirement
40+
41+
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/
42+
43+
## Here are some steps to follow from Visual Studio:
44+
45+
To deploy your function to AWS Lambda, right click the project in Solution Explorer and select *Publish to AWS Lambda*.
46+
47+
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.
48+
49+
To perform testing against your deployed function use the Test Invoke tab in the opened Function View window.
50+
51+
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.
52+
53+
To update the runtime configuration of your deployed function use the Configuration tab in the opened Function View window.
54+
55+
To view execution logs of invocations of your function use the Logs tab in the opened Function View window.
56+
57+
## Here are some steps to follow to get started from the command line:
58+
59+
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
60+
or later is required to deploy this project.
61+
62+
Install Amazon.Lambda.Tools Global Tools if not already installed.
63+
```
64+
dotnet tool install -g Amazon.Lambda.Tools
65+
```
66+
67+
If already installed check if new version is available.
68+
```
69+
dotnet tool update -g Amazon.Lambda.Tools
70+
```
71+
72+
Execute unit tests
73+
```
74+
cd "AOT/test/AOT.Tests"
75+
dotnet test
76+
```
77+
78+
Deploy function to AWS Lambda
79+
```
80+
cd "AOT/src/AOT"
81+
dotnet lambda deploy-function
82+
```
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"Information": [
3+
"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
4+
"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.",
5+
"dotnet lambda help",
6+
"All the command line options for the Lambda command can be specified in this file."
7+
],
8+
"profile": "",
9+
"region": "",
10+
"configuration": "Release",
11+
"function-runtime": "dotnet8",
12+
"function-memory-size": 512,
13+
"function-timeout": 30,
14+
"function-handler": "AOT",
15+
"msbuild-parameters": "--self-contained true"
16+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<ImplicitUsings>enable</ImplicitUsings>
5+
<Nullable>enable</Nullable>
6+
<IsTestProject>true</IsTestProject>
7+
</PropertyGroup>
8+
<ItemGroup>
9+
<PackageReference Include="Amazon.Lambda.Core" Version="2.2.0" />
10+
<PackageReference Include="Amazon.Lambda.TestUtilities" Version="2.0.0" />
11+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
12+
<PackageReference Include="xunit" Version="2.4.2" />
13+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
14+
</ItemGroup>
15+
<ItemGroup>
16+
<ProjectReference Include="..\..\src\AOT\AOT.csproj" />
17+
</ItemGroup>
18+
</Project>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Xunit;
2+
using Amazon.Lambda.Core;
3+
using Amazon.Lambda.TestUtilities;
4+
5+
namespace AOT.Tests;
6+
7+
public class FunctionTest
8+
{
9+
[Fact]
10+
public void TestToUpperFunction()
11+
{
12+
// Invoke the lambda function and confirm the string was upper cased.
13+
var context = new TestLambdaContext();
14+
var upperCase = Function.FunctionHandler("hello world", context);
15+
16+
Assert.Equal("HELLO WORLD", upperCase);
17+
}
18+
}

examples/Metrics/src/HelloWorld/HelloWorld.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.7.0" />
1010
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.4.1" />
1111
<PackageReference Include="AWS.Lambda.Powertools.Logging" Version="1.5.1" />
12-
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.6.2" />
12+
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.7.1" />
1313
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.301.18" />
1414
</ItemGroup>
1515
</Project>

examples/ServerlessApi/src/LambdaPowertoolsAPI/LambdaPowertoolsAPI.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<ItemGroup>
1515
<PackageReference Include="Amazon.Lambda.AspNetCoreServer" Version="9.0.0" />
1616
<PackageReference Include="AWS.Lambda.Powertools.Logging" Version="1.5.1" />
17-
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.6.2" />
17+
<PackageReference Include="AWS.Lambda.Powertools.Metrics" Version="1.7.1" />
1818
<PackageReference Include="AWS.Lambda.Powertools.Tracing" Version="1.4.2" />
1919
</ItemGroup>
2020
</Project>

examples/examples.sln

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CE5C821F-5
7777
EndProject
7878
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld.Tests", "BatchProcessing\test\HelloWorld.Test\HelloWorld.Tests.csproj", "{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}"
7979
EndProject
80+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AOT", "AOT", "{F622EDE4-15EB-4F30-AC63-68E848377F1D}"
81+
EndProject
82+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C765423A-C454-4ABA-B39D-0B527F9BA09A}"
83+
EndProject
84+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E04644BA-719E-40D9-AF91-DA6D412059C7}"
85+
EndProject
86+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOT", "AOT\src\AOT\AOT.csproj", "{0E9D6881-9B32-47C5-89CC-299754D3FD88}"
87+
EndProject
88+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AOT.Tests", "AOT\test\AOT.Tests\AOT.Tests.csproj", "{489F6927-B761-4F11-B8A6-BBD848281698}"
89+
EndProject
8090
Global
8191
GlobalSection(SolutionConfigurationPlatforms) = preSolution
8292
Debug|Any CPU = Debug|Any CPU
@@ -146,6 +156,14 @@ Global
146156
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}.Debug|Any CPU.Build.0 = Debug|Any CPU
147157
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}.Release|Any CPU.ActiveCfg = Release|Any CPU
148158
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88}.Release|Any CPU.Build.0 = Release|Any CPU
159+
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
160+
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Debug|Any CPU.Build.0 = Debug|Any CPU
161+
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Release|Any CPU.ActiveCfg = Release|Any CPU
162+
{0E9D6881-9B32-47C5-89CC-299754D3FD88}.Release|Any CPU.Build.0 = Release|Any CPU
163+
{489F6927-B761-4F11-B8A6-BBD848281698}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
164+
{489F6927-B761-4F11-B8A6-BBD848281698}.Debug|Any CPU.Build.0 = Debug|Any CPU
165+
{489F6927-B761-4F11-B8A6-BBD848281698}.Release|Any CPU.ActiveCfg = Release|Any CPU
166+
{489F6927-B761-4F11-B8A6-BBD848281698}.Release|Any CPU.Build.0 = Release|Any CPU
149167
EndGlobalSection
150168
GlobalSection(NestedProjects) = preSolution
151169
{0CC66DBC-C1DF-4AF6-8EEB-FFED6C578BF4} = {526F1EF7-5A9C-4BFF-ABAE-75992ACD8F78}
@@ -178,5 +196,9 @@ Global
178196
{F33D0918-452F-4AB0-B842-E43AFE6F948D} = {B95EAACA-FBE4-4CC0-B155-D0AD9BCDEE24}
179197
{CE5C821F-5610-490F-B096-EE91F0E34C10} = {2B5E8DE7-8DA4-47B8-81B7-9E269CC77619}
180198
{AAE50681-1FEF-4D9E-9FEA-5406320BDB88} = {CE5C821F-5610-490F-B096-EE91F0E34C10}
199+
{C765423A-C454-4ABA-B39D-0B527F9BA09A} = {F622EDE4-15EB-4F30-AC63-68E848377F1D}
200+
{E04644BA-719E-40D9-AF91-DA6D412059C7} = {F622EDE4-15EB-4F30-AC63-68E848377F1D}
201+
{0E9D6881-9B32-47C5-89CC-299754D3FD88} = {C765423A-C454-4ABA-B39D-0B527F9BA09A}
202+
{489F6927-B761-4F11-B8A6-BBD848281698} = {E04644BA-719E-40D9-AF91-DA6D412059C7}
181203
EndGlobalSection
182204
EndGlobal

0 commit comments

Comments
 (0)