Releases: aws-powertools/powertools-lambda-dotnet
1.50
Summary
We are excited to announce a new integration for Event Handler to work with AWS AppSync Events APIs. This utility provides a structured way to handle AppSync real-time events through dedicated handler methods, automatic routing, and flexible configuration options.
New Event Handler for AppSync Events
The new AppSyncEventsResolver
is designed to streamline working with AWS AppSync real-time APIs by:
- Handling publish and subscribe events with dedicated handler methods
- Routing events automatically based on namespace and channel patterns
- Supporting wildcard patterns for catch-all handlers
- Controlling event aggregation for batch processing
- Implementing graceful error handling
Handling publish events
You can register handlers for publish events using the OnPublish
method and specifying a pattern for the namespace and channels. This is useful when you want to modify payload content, persist the message in a database, or apply business logic and conditionally filter messages out.
Handling subscribe events
You can use the OnSubscribe
method to process subscription requests before allowing clients to connect to specific channels. This enables authorization checks and subscription filtering based on client context or payload attributes, as well as subscription tracking, for example:
Working with aggregated processing
You can use the OnPublishAggregate
method to process multiple events together as a batch. This is useful when you need to optimize database operations, or want to have full control over how the messages are processed.
AppSync Events FAQs
Q: Can I handle different types of events from the same channel?
A: Yes, you can register different handlers for publish and subscribe events on the same channel.
Q: How does handler precedence work with wildcard patterns?
A: More specific patterns take precedence over wildcards. For example, /default/channel1
will be chosen over /default/
, which will be chosen over /
.
Q: What happens when an exception occurs in my handler?
A: With individual processing, the utility catches exceptions and includes them in the response for the specific event while still processing other events. You can also explicitly raise an UnauthorizedException
exception to reject the entire request.
Q: Does the order of async event processing matter?
A: No, AppSync Events doesn't guarantee delivery order. As long as each response includes the original event ID, AppSync processes them correctly regardless of order.
Q: Can I process multiple events as a batch?
A: Yes, use OnPublishAggregate
to receive all matching events as a batch. When doing so, you're responsible implementing the logic to process them and return a list of corresponding items.
Changes
📜 Documentation updates
- chore: Feature/appsync events (#858) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
047452c
to23b6978
in /docs (#830) by @dependabot[bot]
🔧 Maintenance
- chore: Feature/appsync events (#858) by @hjgraca
- chore(deps): bump aws-cdk-lib from 2.186.0 to 2.189.0 (#848) by @dependabot[bot]
- chore(deps): bump actions/setup-node from 4.3.0 to 4.4.0 (#851) by @dependabot[bot]
- chore: update changelog with latest changes (#849) by @hjgraca
- chore(ci): update build_changelog.yml (#847) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
047452c
to23b6978
in /docs (#830) by @dependabot[bot] - chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 3.0.22 to 3.0.23 (#838) by @dependabot[bot]
- chore(deps): bump actions/setup-python from 5.4.0 to 5.5.0 (#837) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.28.10 to 3.28.15 (#836) by @dependabot[bot]
- chore(deps): bump aws-cdk-lib from 2.180.0 to 2.186.0 (#829) by @dependabot[bot]
- chore(deps): bump actions/download-artifact from 4.1.9 to 4.2.1 (#825) by @dependabot[bot]
- chore(deps): bump actions/upload-artifact from 4.6.1 to 4.6.2 (#823) by @dependabot[bot]
This release was made possible by the following contributors:
@dependabot[bot], @hjgraca, Release bot and dependabot[bot]
1.40
Summary
In this release we are excited to announce Logging
2.0.0 developer preview.
This release brings many features requested by customers:
- Support for
ILogger
,LoggerFactory
and builder pattern - Message templating
{@}
and{}
for structured json outputs. - Support for
JsonSerializerOptions
- Log Buffering
- Option to keep the original casing of nested objects
We also releasing version 1.7.0 of Logging
which adds support for cold start on provisioned concurrency and a fix to log level display mismatch in CloudWatch Logs when using Top Level Statement Lambdas (Executable assembly handlers).
Thanks to @nCubed for raising the issue #783
Logging 2.0.0 (developer preview)
Breaking changes from v1
The new major version of the Logging utility introduces several additions without breaking Logger functionality. However, dependency updates are required before upgrading to version 2.x.x.
Breaking changes to dependencies (Action Required)
Change | Before (v1.x) | After (v2.0) | Migration Action |
---|---|---|---|
Amazon.Lambda.Core | 2.2.0 | 2.5.0 | dotnet add package Amazon.Lambda.Core |
Amazon.Lambda.Serialization.SystemTextJson | 2.4.3 | 2.4.4 | dotnet add package Amazon.Lambda.Serialization.SystemTextJson |
Microsoft.Extensions.DependencyInjection | 8.0.0 | 8.0.1 | dotnet add package Microsoft.Extensions.DependencyInjection |
Logger setup
You can now setup the logger in different ways. Before this release the only way was to use the Logging attribute on your Lambda handler. From this release you can now also use the ILogger
or LoggerFactory
that are part of the Microsoft.Extensions.Logging
package.
Using LoggerFactory
Using LoggerFactory gives you more flexibility and testability in case you want to test the Logger as well.
If you are using dependency injection have two constructors one for lambda initialisation and the other for testing or useLambda Annotations that enables a simpler dependency injection mechanism where you don’t require both constructors.
Using Builder pattern
Configuration
You can now configure the Logger outside of the decorator, you can find the full list of properties in our documentation.
This gives you more flexibility, more options, and testability.
Configuring the static Logger in the constructor example:
Configuring using ILogger:
Message Templates
You can now use message templates to extract properties from your objects and log them as structured data.
To take full advantage of message templates, override the ToString() method of your object to return a meaningful string representation of the object.
This is especially important when using {} to log the object as a string.
If you want to log the object as a JSON object, use {@}. This will serialize the object and log it as a JSON object. The Message property will contain the ToString value of that object
If you want to log the object as a string, use {}. This will call the ToString() method of the object and log it as a string.
The .NET composite formatting tokens can be used for formatting parameters. For example, if we have a cost variable with a value of 8.12345 that needs to be rounded to two decimal places in our logging, the logging call would be:
context.Logger.LogInformation("The cost is {cost:0.00}", cost);
This will produce the corresponding JSON document.
Using JsonSerializerOptions
Powertools supports customizing the serialization of Lambda JSON events and your own types using JsonSerializerOptions
. You can do this by creating a custom JsonSerializerOptions
and passing it to the JsonOptions
of the Powertools Logger.
Supports TypeInfoResolver
and DictionaryKeyPolicy
options and others.
These two options are the most common ones used to customize the serialization of Powertools Logger.
- TypeInfoResolver: This option allows you to specify a custom JsonSerializerContext that contains the types you want to serialize and deserialize. This is especially useful when using AOT compilation, as it allows you to specify the types that should be included in the generated assembly.
- DictionaryKeyPolicy: This option allows you to specify a custom naming policy for the properties in the JSON output. This is useful when you want to change the casing of the property names or use a different naming convention.
Preserving the original casing of the properties
If you want to preserve the original casing of the property names (keys), you can set the DictionaryKeyPolicy
to null
.
Log Buffering
Log buffering enables you to buffer logs for a specific request or invocation.
Enable log buffering by passing LogBufferingOptions when configuring a Logger instance. You can buffer logs at the Warning, Information, Debug or Trace level, and flush them automatically on error or manually as needed.
- Buffer logs at the Warning, Information, Debug, and Trace levels
- Automatically flush logs on error or manually as needed. Flushing on error is useful if you would like to get additional context around errors while avoiding emitting verbose logs all the time.
- Reduce CloudWatch costs by decreasing the number of emitted log messages
Configuration options
Option | Description | Default |
---|---|---|
MaxBytes | Maximum size of the log buffer in bytes | 20480 |
BufferAtLogLevel | Minimum log level to buffer (more verbose levels are also buffered) | default |
FlushOnErrorLog | Automatically flush buffer when logging an error | true |
When log buffering is enabled, you can now pass a new opt-in FlushBufferOnUncaughtError flag to the Logger decorator. When enabled, 1/ we'll intercept any error thrown, 2/ flush the buffer, and 3/ re-throw your original error. This enables you to have detailed logs from your application when you need them the most.
Buffering FAQs
- Does the buffer persist across Lambda invocations? No, each Lambda invocation has its own buffer. The buffer is initialized when the Lambda function is invoked and is cleared after the function execution completes or when flushed manually.
- Are my logs buffered during cold starts? No, we never buffer logs during cold starts. This is because we want to ensure that logs emitted during this phase are always available for debugging and monitoring purposes. The buffer is only used during the execution of the Lambda function.
- How can I prevent log buffering from consuming excessive memory? You can limit the size of the buffer by setting the MaxBytes option in the LogBufferingOptions constructor parameter. This will ensure that the buffer does not grow indefinitely and consume excessive memory.
- What happens if the log buffer reaches its maximum size? Older logs are removed from the buffer to make room for new logs. This means that if the buffer is full, you may lose some logs if they are not flushed before the buffer reaches its maximum size. When this happens, we emit a warning when flushing the buffer to indicate that some logs have been dropped.
- How is the log size of a log line calculated? The log size is calculated based on the size of the serialized log line in bytes. This includes the size of the log message, the size of any additional keys, and the size of the timestamp.
- What timestamp is used when I flush the logs? The timestamp preserves the original time when the log record was created. If you create a log record at 11:00:10 and flush it at 11:00:25, the log line will retain its original timestamp of 11:00:10.
- What happens if I try to add a log line that is bigger than max buffer size? The log will be emitted...
1.30
Summary
In this release we are excited to announce a new major release for Metrics
2.0.0 utility and a new Metrics.AspNetCore
package that allows Metrics
to work with Asp.Net projects (minimal api).
We are also releasing a fix to Logging utility, thanks @gregsinclair42 for reporting and contributing a fix. 🥇
Metrics v2.0.0: A major update introducing enhanced flexibility in metrics handling and new initialization patterns NuGet
Metrics.AspNetCore 0.1.0: New package enabling seamless integration with ASP.NET Core projects NuGet - Developer preview
Logging 1.6.5: Improved stability and enhanced Lambda context handling NuGet
Metrics 2.0.0
This new major version of Metrics brings some breaking changes to be aware of when considering a move from v1:
Breaking Changes (Action Required) Docs
Change | Before (v1.x) | After (v2.0) | Migration Action |
---|---|---|---|
Dimensions format | Array of objects: ["service", "Environment"] |
Array of arrays: [["service", "Environment"]] |
Update code that processes dimension outputs |
FunctionName dimension | Added as default dimension to all metrics | Added only to cold start metric | If you relied on FunctionName in all metrics, add it manually |
Cold Start metrics | Default dimensions excluded | Default dimensions included | Update metric queries if you relied on absence of dimensions |
PushSingleMetrics parameters | metricName , defaultDimensions |
name , dimensions |
Update parameter names in method calls |
New features
Environment Variable Control
New: Use POWERTOOLS_METRICS_DISABLED
to disable Metrics functionality completely.
Two new ways of creating a Metrics instance:
Configure Pattern
Builder Pattern
####Adding default dimensions with cold start metric
You can use the Builder or Configure patterns in your Lambda class constructor to set default dimensions.
Push single Metric
Improved: The PushSingleMetric method now publishes completely isolated metrics without dimensions by default.
Benefits:
- Creates metrics that are unaffected by global configuration
- Enables one-off metrics without changing your default setup
Options for adding dimensions:
- Add specific dimensions: dimensions parameter
- Reuse global dimensions:
- Static approach: Metrics.DefaultDimensions
- Instance approach: Options.DefaultDimensions
Cold start function name
You can now customize the FunctionName dimension in Cold Start metrics.
This is useful where you want to maintain the same name in case of auto generated handler names (cdk, top-level statement functions, etc.)
AspNetCore support (Developer preview)
The new AWS.Lambda.Powertools.Metrics.AspNetCore package enables seamless metrics collection in ASP.NET Core applications running on Lambda.
Installation
dotnet add package AWS.Lambda.Powertools.Metrics.AspNetCore
Integration Options
Choose between two approaches for adding metrics to your ASP.NET Core Lambda application:
UseMetrics Middleware
The UseMetrics middleware is an extension method for the IApplicationBuilder interface.
It adds a metrics middleware to the specified application builder, which captures cold start metrics (if enabled) and flushes metrics on function exit.
WithMetrics Filter
The WithMetrics method is an extension method for the RouteHandlerBuilder class.
It adds a metrics filter to the specified route handler builder, which captures cold start metrics (if enabled) and flushes metrics on function exit.
Testing improvements
To test your code that uses the Metrics utility, you can use the TestLambdaContext class from the Amazon.Lambda.TestUtilities package.
You can now use the IMetrics interface to mock the Metrics utility in your tests.
Logging 1.6.5
Issue Fixed
Improved validation of ILambdaContext parameters regardless of position in method signature.
Before: The Logging utility only checked if ILambdaContext was null when it was the first parameter.
After: The utility now properly validates ILambdaContext at any position in the method signature.
Benefits
- Simplified testing: Unit tests can now pass null for ILambdaContext parameters
- More robust error handling: Prevents runtime exceptions when invalid contexts are provided
- Consistent behavior: Context validation works the same way regardless of parameter position
User experience
Previously, unit tests could be hard to write if a method we call had the [Logging] attribute on it, because then we had to ensure the LambdaContext was set and valid. Now we don't have to worry about the lambda context and can just focus on the code.
This would occur if there was a method like:
Changes
📜 Documentation updates
- chore(deps): bump jinja2 from 3.1.5 to 3.1.6 in /docs (#804) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
2615302
to047452c
in /docs (#801) by @dependabot[bot] - chore(metrics): Fix low hanging fruit for v2 (#800) by @hjgraca
- chore: Metrics disabled environment variable (#786) by @hjgraca
- chore: Metrics set custom FunctionName cold start dimension (#785) by @hjgraca
- chore: Metrics PushSingleMetric default dimensions (#780) by @hjgraca
- chore: Metrics AspNetCore support (#775) by @hjgraca
- chore: Add sitemap to documentation website (#767) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
f5bcec4
to2615302
in /docs (#770) by @dependabot[bot] - fix(ci): Permissions and depdendencies (#772) by @sthulb
- chore(deps): bump squidfunk/mkdocs-material from
c62453b
tof5bcec4
in /docs (#764) by @dependabot[bot]
🐛 Bug and hot fixes
- fix: Metrics e2e tests (#802) by @hjgraca
- fix(logging): check if ILambdaContext is valid in LoggingLambdaContext.Extract (#791) by @gregsinclair42
- fix(ci): add write for issues (#789) by @sthulb
- fix(ci): Add permissions to read issues and pull requests (#788) by @sthulb
- fix(ci): Indentation issue (on_label_added) (#787) by @sthulb
- fix(ci): Permissions (#782) by @sthulb
- fix(ci): Permissions and depdendencies (#772) by @sthulb
🔧 Maintenance
- chore: Update version of logging for release (#811) by @hjgraca
- chore: add contents: write to release drafter (#810) by @hjgraca
- chore: Metrics v2 always set namespace and service (#807) by @hjgraca
- chore(deps): bump jinja2 from 3.1.5 to 3.1.6 (#805) by @dependabot[bot]
- chore(deps): bump jinja2 from 3.1.5 to 3.1.6 in /docs (#804) by @dependabot[bot]
- fix: Metrics e2e tests (#802) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
2615302
to047452c
in /docs (#801) by @dependabot[bot] - chore(metrics): Fix low hanging fruit for v2 (#800) by @hjgraca
- chore: Update GitHub workflows from main to develop (#799) by @hjgraca
- chore: Remove trailing comma (#797) by @hjgraca
- chore(deps): bump codecov/codecov-action from 5.3.1 to 5.4.0 (#793) by @dependabot[bot]
- chore: Metrics disabled environment variable (#786) by @hjgraca
- chore: Metrics set custom FunctionName cold start dimension (#785) by @hjgraca
- chore: Metrics PushSingleMetric default dimensions (#780) by @hjgraca
- chore: Metrics AspNetCore support (#775) by @hjgraca
- chore: Feature/metrics default dimensions coldstart (#771) by @hjgraca
- chore: Add openssf scorecard badge to readme (#790) by @HJ...
1.20
Summary
As part of our ongoing effort to make Powertools fully AOT compatible, we're thrilled to announce Idempotency support for native ahead-of-time (AOT) compilation.
Additionally, we've introduced custom key prefix support for Idempotency.
We've also addressed a bug in our Tracing utility that affected implementations using Top Level Statements.
Special thanks to @nCubed for bringing the Tracing issue to our attention.
Idempotency AOT
To enable Idempotency utility with AOT support, you need to configure the serialization context by adding WithJsonSerializationContext() to your Idempotency configuration.
In the example below, we use the default LambdaFunctionJsonSerializerContext. If you're using the Logging utility, you can alternatively use the PowertoolsSourceGeneratorSerializer.For more information visit our documentation
Idempotency.Configure(builder =>
builder.WithJsonSerializationContext(LambdaFunctionJsonSerializerContext.Default)));
Full example
public static class Function
{
private static async Task Main()
{
var tableName = Environment.GetEnvironmentVariable("IDEMPOTENCY_TABLE_NAME");
Idempotency.Configure(builder =>
builder
.WithJsonSerializationContext(LambdaFunctionJsonSerializerContext.Default)
.WithOptions(optionsBuilder => optionsBuilder
.WithExpiration(TimeSpan.FromHours(1)))
.UseDynamoDb(storeBuilder => storeBuilder
.WithTableName(tableName)
));
Func<APIGatewayProxyRequest, ILambdaContext, APIGatewayProxyResponse> handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler,
new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>())
.Build()
.RunAsync();
}
[Idempotent]
public static APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest apigwProxyEvent,
ILambdaContext context)
{
return new APIGatewayProxyResponse
{
Body = JsonSerializer.Serialize(response, typeof(Response), LambdaFunctionJsonSerializerContext.Default),
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
}
[JsonSerializable(typeof(APIGatewayProxyRequest))]
[JsonSerializable(typeof(APIGatewayProxyResponse))]
[JsonSerializable(typeof(Response))]
public partial class LambdaFunctionJsonSerializerContext : JsonSerializerContext
{
}
Idempotency custom key prefix
By default, the idempotency key follows the format [ClassName].[DecoratedMethodName]#[PayloadHash].
With this release, You can now customize this prefix by setting the KeyPrefix property in the Idempotency decorator, making code refactoring more manageable without impacting existing idempotency items.
public class Function
{
public Function()
{
var tableName = Environment.GetEnvironmentVariable("IDEMPOTENCY_TABLE_NAME");
Idempotency.Configure(builder => builder.UseDynamoDb(tableName));
}
[Idempotent(KeyPrefix = "MyCustomKeyPrefix")]
public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest apigwProxyEvent, ILambdaContext context)
{
return TestHelper.TestMethod(apigwProxyEvent);
}
}
Tracing segment name sanitization
Tracing segment name docs and X-Ray docs
Previously, string names automatically generated from Tracing-decorated methods weren't sanitized, which could silently fail and prevent traces from appearing in X-Ray due to invalid characters. While this could be addressed by specifying a custom segment name in the Tracing decorator, the custom string itself might still contain invalid characters.
To resolve this, we've implemented two improvements:
- Added documentation describing valid characters for segment names
- Implemented automatic string sanitization for both auto-generated and custom segment names
These changes ensure that no traces are dropped due to invalid characters in segment names, maintaining reliable trace data collection in X-Ray.
/// <summary>
/// Set custom segment name for the operation.
/// The default is '## {MethodName}'.
///
/// The logical name of the service that handled the request, up to 200 characters.
/// Names can contain Unicode letters, numbers, and whitespace, and the following symbols: \_, ., :, /, %, &, #, =, +, \\, -, @
/// </summary>
public string SegmentName { get; set; } = "";
using System.Text.RegularExpressions;
public static string SanitizeString(string input)
{
// Define a regular expression pattern to match allowed characters
string pattern = @"[^a-zA-Z0-9\s_\.\:/%&#=+\-@]";
// Replace any character that does not match the pattern with an empty string
return Regex.Replace(input, pattern, string.Empty);
}
Changes
📜 Documentation updates
- chore: Roadmap 2025 update (#757) by @hjgraca
- chore: Update docs Idempotency custom prefix (#758) by @hjgraca
- chore: Sync main with develop for release 1.20 (#752) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
7e841df
toc62453b
in /docs (#748) by @dependabot[bot] - chore: Add privacy plugin to mkdocs (#747) by @hjgraca
- chore: AOT support for Idempotency (#653) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
471695f
to7e841df
in /docs (#744) by @dependabot[bot] - chore(deps): bump squidfunk/mkdocs-material from
41942f7
to471695f
in /docs (#739) by @dependabot[bot]
🔧 Maintenance
- chore(deps): bump aws-actions/configure-aws-credentials from 4.0.3 to 4.1.0 (#755) by @dependabot[bot]
- chore(deps): bump actions/upload-artifact from 4.5.0 to 4.6.0 (#754) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.27.9 to 3.28.9 (#753) by @dependabot[bot]
- chore: Roadmap 2025 update (#757) by @hjgraca
- chore: Update docs Idempotency custom prefix (#758) by @hjgraca
- chore: Sync main with develop for release 1.20 (#752) by @hjgraca
- chore: update versions for release 1.20 (#743) by @hjgraca
- chore(deps): bump pygments from 2.13.0 to 2.15.0 (#355) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.28.8 to 3.28.9 (#751) by @dependabot[bot]
- chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 3.0.20 to 3.0.21 (#750) by @dependabot[bot]
- chore(deps): bump squidfunk/mkdocs-material from
7e841df
toc62453b
in /docs (#748) by @dependabot[bot] - chore: Add support for custom key prefixes in Idempotency utility (#745) by @hjgraca
- chore: Add privacy plugin to mkdocs (#747) by @hjgraca
- chore: AOT support for Idempotency (#653) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
471695f
to7e841df
in /docs (#744) by @dependabot[bot] - chore: idempotency e2e tests (#738) by @hjgraca
- chore: Tracing Sanitize SegmentName to avoid unsupported characters (#741) by @hjgraca
- chore(deps): bump squidfunk/mkdocs-material from
41942f7
to471695f
in /docs (#739) by @dependabot[bot] - chore(deps): bump actions/setup-dotnet from 4.2.0 to 4.3.0 (#736) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.28.6 to 3.28.8 (#737) by @dependabot[bot]
- chore: Update api docs build to dotnet 8 (#734) by @hjgraca
- chore(deps): bump github/codeql-action from 3.28.5 to 3.28.6 (#727) by @dependabot[bot]
- chore(deps): bump aws-actions/configure-aws-credentials from 4.0.2 to 4.0.3 (#725) by @dependabot[bot]
- chore(deps): bump actions/setup-python from 5.3.0 to 5.4.0 (#726) by @dependabot[bot]
- chore: Update test projects to no be packable (#731) by @hjgraca
This release was made possible by the following contributors:
@dependabot[bot], @hjgraca and dependabot[bot]
1.19
Summary
This release addresses a regression introduced in version 1.6.0 of the Logging utility. The bug prevented the Service property from being updated after the initial Logger instantiation, even when set through the Handler.
Special thanks to @nCubed for reporting this issue (#702) and huge thanks to our first-time contributor @ankitdhaka07!
We greatly appreciate your contributions!
Service Property Priority Resolution
The root level Service property now correctly follows this priority order:
- LoggingAttribute.Service (property value set in the decorator)
POWERTOOLS_SERVICE_NAME
(environment variable)
Previously, if the Logger was initialized before the handler execution and the POWERTOOLS_SERVICE_NAME
environment variable was set, the service value would remain unchanged even when the handler decorator specified a different value.
This release ensures that the Service property is correctly updated according to the priority resolution order, allowing the decorator's value to take precedence when specified.
Changes
📜 Documentation updates
- chore: add Logging Service property priority to docs (#728) by @hjgraca
- chore(ci): add dependabot file (#706) by @leandrodamascena
🐛 Bug and hot fixes
- fix: pin FluentAssertions NuGet version to prevent license issues (#698) by @ankitdhaka07
🔧 Maintenance
- chore: Update Logging version for release 1.19 (#724) by @hjgraca
- chore: Fix Service override on decorator (#704) by @hjgraca
- chore(deps): bump codecov/codecov-action from 5.3.0 to 5.3.1 (#722) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 3.28.4 to 3.28.5 (#721) by @dependabot[bot]
- chore(deps): bump codecov/codecov-action from 4.5.0 to 5.3.0 (#714) by @dependabot[bot]
- chore(deps): bump release-drafter/release-drafter from 5.21.1 to 6.1.0 (#715) by @dependabot[bot]
- chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 1.3.0 to 3.0.20 (#716) by @dependabot[bot]
- chore(deps): bump actions/checkout from 4.1.7 to 4.2.2 (#717) by @dependabot[bot]
- chore: Only run on libraries folder changes (#720) by @hjgraca
- chore(deps): bump actions/upload-artifact from 4.5.0 to 4.6.0 (#718) by @dependabot[bot]
- chore: Add concurrency to e2e workflow (#713) by @hjgraca
- chore(deps): bump actions/setup-dotnet from 3.0.3 to 4.2.0 (#707) by @dependabot[bot]
- chore(deps): bump aws-actions/configure-aws-credentials from 2.0.0 to 4.0.2 (#708) by @dependabot[bot]
- chore(deps): bump actions/github-script from 6 to 7 (#711) by @dependabot[bot]
- chore(deps): bump github/codeql-action from 2.1.18 to 3.28.4 (#710) by @dependabot[bot]
- chore(deps): bump actions/upload-artifact from 3 to 4 (#709) by @dependabot[bot]
- chore(ci): add dependabot file (#706) by @leandrodamascena
- chore: Fix arm e2e aot (#700) by @hjgraca
- chore: Update dependencies for examples release 1.17 (#679) by @hjgraca
- chore: Bump jinja2 from 3.1.4 to 3.1.5 (#682) by @dependabot[bot]
- chore: Add Aot e2e tests for x86 (#699) by @hjgraca
This release was made possible by the following contributors:
@ankitdhaka07, @dependabot[bot], @hjgraca, @leandrodamascena, dependabot[bot]
1.18
Summary
In this release we added support for structured logging of inner exceptions in the Logging utility.
This feature is available starting on version 1.6.3 of Logging
⭐ Thank you @joaope for the feature request
Include inner exceptions in error messages
Before
{
"exception": {
"type": "System.InvalidOperationException",
"message": "Parent exception message"
}
}
After
{
"exception": {
"type": "System.InvalidOperationException",
"message": "Parent exception message",
"inner_exception": {
"type": "System.ArgumentNullException",
"message": "Very important inner exception message"
}
}
}
Usage Example
Logger.LogError(
new InvalidOperationException("Parent message",
new ArgumentNullException("input", "Inner message")),
"Operation failed with {arg}",
12345
);
Changes
🔧 Maintenance
- chore: Add e2e tests (#692) by @hjgraca
- chore: Update e2e-tests.yml (#691) by @hjgraca
- chore: Add workflow call to e2e tests (#685) by @hjgraca
- chore: Add end-to-end tests (#684) by @hjgraca
- chore: Exception logging to include inner exceptions (#681) by @hjgraca
This release was made possible by the following contributors:
1.17
Summary
AWS Lambda Powertools for .NET - Tracing 1.6.0
🐛 Bug Fixes
- Fixed a NotSupportedException that occurred when using the Tracing utility in native AOT mode with async methods that don't return a value (Task)
- Special thanks to @matthewwilson for reporting this issue! ⭐
📦 Package Information
- Version: 1.6.0
- Package: AWS.Lambda.Powertools.Tracing
Native AOT Support
Important
To allow Tracing to work with your types in native AOT mode, you must add **WithTracing()**
to your source generator configuration. This works with either:
- The default SourceGeneratorLambdaJsonSerializer
- The Powertools Logging utility source generator PowertoolsSourceGeneratorSerializer
Tip
For detailed implementation guidelines, please refer to our AOT support documentation.
Implementation Examples
Using Default Source Generator
using AWS.Lambda.Powertools.Tracing;
using AWS.Lambda.Powertools.Tracing.Serializers;
private static async Task Main()
{
Func<string, ILambdaContext, string> handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer<LambdaFunctionJsonSerializerContext>()
.WithTracing())
.Build()
.RunAsync();
}
Using Powertools Logging Source Generator
using AWS.Lambda.Powertools.Logging;
using AWS.Lambda.Powertools.Logging.Serializers;
using AWS.Lambda.Powertools.Tracing;
using AWS.Lambda.Powertools.Tracing.Serializers;
private static async Task Main()
{
Func<string, ILambdaContext, string> handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler,
new PowertoolsSourceGeneratorSerializer<LambdaFunctionJsonSerializerContext>()
.WithTracing())
.Build()
.RunAsync();
}
Changes
📜 Documentation updates
🔧 Maintenance
This release was made possible by the following contributors:
1.16
Summary
In this release we have fixed an issue with Enum serialization.
The fix addresses an edge case where enum values weren't properly serialized when using C# top-level statements (file-scoped namespaces) in Lambda functions. This ensures proper logging functionality regardless of your chosen code structure.
Logging version: 1.6.2
- Fixed Enum serialization when using top-level statements in Lambda functions
- Resolves incorrect enum value handling in structured logging
- Ensures consistent logging behavior across different Lambda function styles
Special thanks to @nCubed for:
- Reporting the issue
- Providing detailed reproduction steps
- Assisting with troubleshooting and validation
Changes
🐞 Fixes
This release was made possible by the following contributors:
1.15
Summary
In this release we are excited to announce a new feature in the Batch processing utility and bug fixes in Tracing and Logging.
New Feature: ThrowOnFullBatchFailure
This release introduces a new batch processing option: ThrowOnFullBatchFailure
. This option controls whether a BatchProcessingException
should be raised on full batch failure.
⭐ Special thanks to @lachriz-aws for developing this feature.
The ThrowOnFullBatchFailure
option can be set via:
- A new
ThrowOnFullBatchFailure
field on theBatchProcessor
attribute (applied in non-utility mode) - A new environment variable
POWERTOOLS_BATCH_THROW_ON_FULL_BATCH_FAILURE
(applied in non-utility mode) - Directly on the
AWS.Lambda.Powertools.BatchProcessing.ProcessingOptions
in utility mode
Behavior
When processing of an entire batch fails:
- If
ThrowOnFullBatchFailure
is set tofalse
, the Batch Processor will not throw an exception after batch processing has completed. Instead, it will return the IDs of the failed items (all batch items in this case) and exit gracefully. - If a Lambda function is configured with
ErrorHandlingPolicy = StopOnFirstBatchItemFailure
and the first batch item fails processing, the entire batch is marked as failed (as per the documentation). In this case, ifThrowOnFullBatchFailure
is set tofalse
, the behavior described above will apply.
Note: The new ThrowOnFullBatchFailure
option is compatible with the existing error handling policies.
Bug Fixes
Tracing Update
- Updated to version 1.5.2
- Fixed issue #659: Lambda timeout when calling async methods from a
Tracing
decorated method in version 1.5.1 - Thanks to @JonathanVerberne for reporting this issue
Logging Update
- Updated to version 1.6.1
- Fixed issue #656: Serialization exceptions when running .NET 8 non-AOT Lambda functions
- Thanks to @nCubed for reporting this issue
Changes
🌟New features and non-breaking changes
- feat: New batch processing option: 'ThrowOnFullBatchFailure' (#646) by @lachriz-aws
📜 Documentation updates
- feat: New batch processing option: 'ThrowOnFullBatchFailure' (#646) by @lachriz-aws
🔧 Bug Fixes
- chore: Fix Lambda timeout with Tracing 1.5.1 using async methods (#660) by @hjgraca
- chore: Remove TypeInfoResolver from non AOT mode. (#657) by @hjgraca
- chore: update logging nuget package version v 1.6.0 (#652) by @hjgraca
This release was made possible by the following contributors:
@hjgraca and @lachriz-aws
1.14
Summary
We are excited to announce GA support for Ahead-of-Time (AOT) compilation for Logging version 1.6.0. You can now use Logging in your AOT-published .NET AWS Lambda functions without any AOT warnings.
With this release, all Powertools core utilities (Logging, Metrics, and Tracing) have AOT support.
You can follow progress on AOT support here.
Check our docs for AOT support details.
Tip
New to AOT?
Check out this tutorial in the AWS Lambda documentation.
Serialization
Important
Starting from version 1.6.0, it is required to update the Amazon.Lambda.Serialization.SystemTextJson
NuGet package to version 2.4.3
in your csproj
.
Note
Using LogEvent
, Custom Log Formatter
features, or serialize your own types when Logging events? You need to make changes in your Lambda Main
method.
Replace SourceGeneratorLambdaJsonSerializer
with PowertoolsSourceGeneratorSerializer
.
When you update your code to use PowertoolsSourceGeneratorSerializer<MyCustomJsonSerializerContext>
, we combine your JsonSerializerContext
with Powertools' JsonSerializerContext
. This allows Powertools to serialize your types and Lambda events.
Custom Log Formatter
Important
To use a custom log formatter with AOT, pass an instance of ILogFormatter
to PowertoolsSourceGeneratorSerializer
instead of using the static Logger.UseFormatter
in the Function constructor as you do in non-AOT Lambdas.
Anonymous Types
While we support anonymous type serialization by converting to a Dictionary<string, object>
, this is not a best practice and is not recommended when using native AOT.
We recommend using concrete classes and adding them to your JsonSerializerContext
.
Changes
🚀 Features
📜 Documentation updates
🔧 Maintenance
- chore: Update examples for release 1..13 (#645) by @hjgraca
- chore: Refactor and simplify Common dependency. (#643) by @hjgraca
- chore: Change the way we reference Common and JMESPath (internal references). (#641) by @hjgraca